1

I'm trying to have an interface which declares that a property must have a get:

public interface IValue {
    public int Value { get; }
}

And then have an abstract class also define it, but keep it abstract:

public abstract class BaseClass : IValue {
    public abstract int Value { get; }
}

And then I want to allow a subclass to define the getter and add a setter:

public class SubClass : BaseClass {
    public int Value { get; set; }
}

I get an error like:

'SubClass.Value' hides inherited member `BaseClass.Value'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword

If I try:

public class SubClass : BaseClass {
    public override int Value { get; set; }
}

I get:

`SubClass.Value.set': cannot override because `BaseClass.Value' does not have an overridable set accessor

Is there any way to allow a subclass to optionally add a setter when inheriting from an abstract class that only defines a getter?

Update: Just to clarify, I know of the workarounds I can do. My goal was to see what's the cleanest way I can do this. The reason I don't just throw a public setter on BaseClass is because some subclasses of BaseClass may not have a public setter. The end goal is basically just provide a common Value getter for the times they're used commonly.

samanime
  • 25,408
  • 15
  • 90
  • 139

3 Answers3

1
  1. 'SubClass.Value' hides inherited member 'BaseClass.Value'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword

Is a warning not an error. It just says that you have public int Value in both abstract and concrete classes. Your abstract class has implementation of this property so when you declare it again in concrete class you just replace it with new property. So compiler advice you to use 'new' word for that purpose.

  1. To use public override int Value { get; set; } you have to mark it 'virtual' in base class. Only virtual members can be overriden.

    Class A { public virtual int Value { get; set; } } Class B : A { public override int Value { get; set; } }

P.S. Interface members are public and abstract by default. So if you declare getter and setter in interface - you have to implement it in a concrete class.

Try to use this code:

public interface IValue
{
    int Value { get; set; }
}

public abstract class BaseClass
{
    int value;
    int Value { get { return value; } }
}

public class SubClass : BaseClass, IValue
{
    public int Value { get { return Value; } set { this.Value = value; } }
}
Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • Sorry, forgot that. I updated it above. BaseClass should implement IValue. – samanime Jun 18 '15 at 09:41
  • That doesn't quite work, because I don't want the IValue to say there is a setter, as some subclasses of BaseClass or some implementing classes of IValue won't have setters, only getters. – samanime Jun 18 '15 at 18:57
  • Sometimes, it is indeed good to use a private setter. The only problem is in this particular case, I need to have a public setter for certain subclasses. – samanime Jun 18 '15 at 23:32
1

You can't override getter, and add new setter. This is what your code is, when properties are compiled into get_Value and set_Value methods:

public interface IValue
{
    int get_Value();
}

public abstract class BaseClass : IValue
{
    public abstract int get_Value();
}

public class SubClass : BaseClass
{
    public override int get_Value() { /* ... */ }

    // there's no set_Value method to override in base class
    public override void set_Value(int value) { /* ... */ }
}

There are at least three ways:

  • define new int Value property in SubClass (note, then there's a difference);
  • override Value property and add SetValue method in SubClass;
  • define setter in BaseClass and override property.
Community
  • 1
  • 1
Dennis
  • 37,026
  • 10
  • 82
  • 150
  • Thanks Dennis. I knew what was going on, but I hoped this was some syntax that would allow me to override just one of the two (since they really are just two functions). The differences with the new value aren't acceptable for this particular implementation, so I ended up going with the second one. If you would add a quick code sample for option 2 (you can even copy/paste mine below), I'll accept this as the answer. Thanks. – samanime Jun 18 '15 at 19:10
0

It appears there simply isn't a way to add the set with an abstract class in the middle without declaring a setter up-front. I've tried a ton of different combinations, and no luck.

Finally, I ended up doing this, which isn't ideal, but at least lets me not have a setter everywhere.

public interface IValue {
    public int Value { get; }
}

public abstract class BaseClass : IValue {
    public abstract int Value { get; }
}

public class SubClass : BaseClass {
    protected int val;
    public int Value { get { return val; } }
    public int SetValue (int value) { val = value; }
}

public class SubClassWithoutSetter : BaseClass {
    public int Value { get { return 50; } }
}

Basically, just do a "classic" setter, since there doesn't seem to be a syntax that supports letting me add a setter property after the fact.

It'd be nice if C# would implement something like:

public int Value { override get; set; } // note: this does not work
samanime
  • 25,408
  • 15
  • 90
  • 139