160

Why is the following C# code not allowed:

public abstract class BaseClass
{
    public abstract int Bar { get;}
}

public class ConcreteClass : BaseClass
{
    public override int Bar
    {
        get { return 0; }
        set {}
    }
}

CS0546 'ConcreteClass.Bar.set': cannot override because 'BaseClass.Bar' does not have an overridable set accessor

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
ripper234
  • 222,824
  • 274
  • 634
  • 905
  • 11
    StackOverflow has limited ability to answer questions on behalf of Microsoft. Consider rephrasing your question. – Jay Bazuzi Sep 18 '08 at 03:59
  • 1
    Incidentally, a simple remedy for this annoying behavior in .net is to have a non-virtual read-only property `Foo` which does nothing but wrap a protected abstract `GetFoo` method. An abstract derived type can shadow the property with a non-virtual read-write property which does nothing but wrap the aforementioned `GetFoo` method along with an abstract `SetFoo` method; a concrete derived type could do the above but supply definitions for `GetFoo` and `SetFoo`. – supercat Oct 30 '12 at 19:33
  • 2
    Just to add fuel to the fire, C++/CLI does allow this. – ymett Nov 14 '16 at 13:50
  • 1
    The ability to add an accessor when overriding a property has been proposed as a change for a future version of C# (https://github.com/dotnet/roslyn/issues/9482). – Brandon Bonds Dec 16 '16 at 22:24
  • 1
    To be frank, this question is often raised when there's need to extend an existing library type that uses the following pattern: read-only base class, derived mutable class. Because the library already uses a bad pattern (such as WPF), the need arise to workaround this bad pattern. Lecturing doesn't save one from having to implement a workaround at the end of the day. – rwong Nov 01 '17 at 00:41
  • I think a better answer than the “accepted” one is [Roman Starkov’s](https://stackoverflow.com/a/2571197) because he actually gives a believable reason for why MS doesn’t support `T Property { override get => p; set => p = value; }` which is that, among other things, it would have cost a lot to add it. – binki Dec 28 '17 at 15:24
  • This seems to be a restriction in C# similar to [increasing visibility being disallowed when overriding](https://stackoverflow.com/q/6236909/429091). – binki Dec 28 '17 at 15:49
  • This is frustrating until you realize this line is completely legit: `public override int Bar { get; }` Then it becomes laughable. C# does let you override with an auto-getter, but doesn't let you assign it a value, ever! – David Augusto Villa Nov 12 '19 at 18:53

16 Answers16

47

I think the main reason is simply that the syntax is too explicit for this to work any other way. This code:

public override int MyProperty { get { ... } set { ... } }

is quite explicit that both the get and the set are overrides. There is no set in the base class, so the compiler complains. Just like you can't override a method that's not defined in the base class, you can't override a setter either.

You might say that the compiler should guess your intention and only apply the override to the method that can be overridden (i.e. the getter in this case), but this goes against one of the C# design principles - that the compiler must not guess your intentions, because it may guess wrong without you knowing.

I think the following syntax might do nicely, but as Eric Lippert keeps saying, implementing even a minor feature like this is still a major amount of effort...

public int MyProperty
{
    override get { ... } // not valid C#
    set { ... }
}

or, for autoimplemented properties,

public int MyProperty { override get; set; } // not valid C#
Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
  • This unfortunately doesn't work if your class implements an interface. In that case you will get a [CS0106](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0106) compiler warning sayig `The modifier 'override' is not valid for this item`. – Roald Oct 30 '20 at 09:13
  • "The modifier 'override' is not valid for this item" Compiler raising issue – logeshpalani31 Apr 12 '21 at 19:31
  • 2
    @logeshpalani98 that's right. This is not currently possible in C#. My examples were imaginary. – Roman Starkov Apr 13 '21 at 05:16
31

It's possible.

tl;dr You can override a get-only method with a setter if you want. It's basically just:

  1. Create a new property that has both a get and a set using the same name.

  2. override the prior get to alias the new get.

This enables us to override properties with get/set even if they lacked a setter in their base definition.


Situation: Pre-existing get-only property.

You have some class structure that you can't modify. Maybe it's just one class, or it's a pre-existing inheritance tree. Whatever the case, you want to add a set method to a property, but can't.

public abstract class A                     // Pre-existing class; can't modify
{
    public abstract int X { get; }          // You want a setter, but can't add it.
}
public class B : A                          // Pre-existing class; can't modify
{
    public override int X { get { return 0; } }
}

Problem: Can't override the get-only with get/set.

You want to override with a get/set property, but it won't compile.

public class C : B
{
    private int _x;
    public override int X
    {
        get { return _x; }
        set { _x = value; }   //  Won't compile
    }
}

Solution: Use an abstract intermediate layer.

While you can't directly override with a get/set property, you can:

  1. Create a new get/set property with the same name.

  2. override the old get method with an accessor to the new get method to ensure consistency.

So, first you write the abstract intermediate layer:

public abstract class C : B
{
    //  Seal off the old getter.  From now on, its only job
    //  is to alias the new getter in the base classes.
    public sealed override int X { get { return this.XGetter; }  }
    protected abstract int XGetter { get; }
}

Then, you write the class that wouldn't compile earlier. It'll compile this time because you're not actually override'ing the get-only property; instead, you're replacing it using the new keyword.

public class D : C
{
    private int _x;
    public new virtual int X
    {
        get { return this._x; }
        set { this._x = value; }
    }

    //  Ensure base classes (A,B,C) use the new get method.
    protected sealed override int XGetter { get { return this.X; } }
}

Result: Everything works!

var d = new D();

var a = d as A;
var b = d as B;
var c = d as C;

Print(a.X);      // Prints "0", the default value of an int.
Print(b.X);      // Prints "0", the default value of an int.
Print(c.X);      // Prints "0", the default value of an int.
Print(d.X);      // Prints "0", the default value of an int.

// a.X = 7;      // Won't compile: A.X doesn't have a setter.
// b.X = 7;      // Won't compile: B.X doesn't have a setter.
// c.X = 7;      // Won't compile: C.X doesn't have a setter.
d.X = 7;         // Compiles, because D.X does have a setter.

Print(a.X);      // Prints "7", because 7 was set through D.X.
Print(b.X);      // Prints "7", because 7 was set through D.X.
Print(c.X);      // Prints "7", because 7 was set through D.X.
Print(d.X);      // Prints "7", because 7 was set through D.X.

Discussion.

This method allows you to add set methods to get-only properties. You can also use it to do stuff like:

  1. Change any property into a get-only, set-only, or get-and-set property, regardless of what it was in a base class.

  2. Change the return type of a method in derived classes.

The main drawbacks are that there's more coding to do and an extra abstract class in the inheritance tree. This can be a bit annoying with constructors that take parameters because those have to be copy/pasted in the intermediate layer.


Bonus: You can change the property's return-type.

As a bonus, you can also change the return type if you want.

  • If the base definition was get-only, then you can use a more-derived return type.

  • If the base definition was set-only, then you can use a less-derived return type.

  • If the base definition was already get/set, then:

    • you can use a more-derived return type if you make it set-only;

    • you can use a less-derived return type if you make it get-only.

In all cases, you can keep the same return type if you want.

Nat
  • 1,085
  • 2
  • 18
  • 35
22

I stumbled across the very same problem today and I think I have a very valid reason for wanting this.

First I'd like to argue that having a get-only property doesn't necessarily translate into read-only. I interpret it as "From this interface/abstract class you can get this value", that doesn't mean that some implementation of that interface/abstract class won't need the user/program to set this value explicitly. Abstract classes serve the purpose of implementing part of the needed functionality. I see absolutely no reason why an inherited class couldn't add a setter without violating any contracts.

The following is a simplified example of what I needed today. I ended up having to add a setter in my interface just to get around this. The reason for adding the setter and not adding, say, a SetProp method is that one particular implementation of the interface used DataContract/DataMember for serialization of Prop, which would have been made needlessly complicated if I had to add another property just for the purpose of serialization.

interface ITest
{
    // Other stuff
    string Prop { get; }
}

// Implements other stuff
abstract class ATest : ITest
{
    abstract public string Prop { get; }
}

// This implementation of ITest needs the user to set the value of Prop
class BTest : ATest
{
    string foo = "BTest";
    public override string Prop
    {
        get { return foo; }
        set { foo = value; } // Not allowed. 'BTest.Prop.set': cannot override because 'ATest.Prop' does not have an overridable set accessor
    }
}

// This implementation of ITest generates the value for Prop itself
class CTest : ATest
{
    string foo = "CTest";
    public override string Prop
    {
        get { return foo; }
        // set; // Not needed
    }
}

I know this is just a "my 2 cents" post, but I feel with the original poster and trying to rationalize that this is a good thing seems odd to me, especially considering that the same limitations doesn't apply when inheriting directly from an interface.

Also the mention about using new instead of override does not apply here, it simply doesn't work and even if it did it wouldn't give you the result wanted, namely a virtual getter as described by the interface.

Pang
  • 9,564
  • 146
  • 81
  • 122
JJJ
  • 509
  • 1
  • 6
  • 14
  • 3
    Or, in my case, { get; private set; }. I'm not violating any contract as the set remains private and is only concerned with the derivative class. – Machtyn Apr 30 '15 at 19:37
  • 'BTest.Prop.set': cannot override because 'ATest.Prop' does not have an overridable set accessor – logeshpalani31 Apr 12 '21 at 19:33
12

I agree that not being able to override a getter in a derived type is an anti-pattern. Read-Only specifies lack of implementation, not a contract of a pure functional (implied by the top vote answer).

I suspect Microsoft had this limitation either because the same misconception was promoted, or perhaps because of simplifying grammar; though, now that scope can be applied to get or set individually, perhaps we can hope override can be too.

The misconception indicated by the top vote answer, that a read-only property should somehow be more "pure" than a read/write property is ridiculous. Simply look at many common read only properties in the framework; the value is not a constant / purely functional; for example, DateTime.Now is read-only, but anything but a pure functional value. An attempt to 'cache' a value of a read only property assuming it will return the same value next time is risky.

In any case, I've used one of the following strategies to overcome this limitation; both are less than perfect, but will allow you to limp beyond this language deficiency:

   class BaseType
   {
      public virtual T LastRequest { get {...} }
   }

   class DerivedTypeStrategy1
   {
      /// get or set the value returned by the LastRequest property.
      public bool T LastRequestValue { get; set; }

      public override T LastRequest { get { return LastRequestValue; } }
   }

   class DerivedTypeStrategy2
   {
      /// set the value returned by the LastRequest property.
      public bool SetLastRequest( T value ) { this._x = value; }

      public override T LastRequest { get { return _x; } }

      private bool _x;
   }
T.Tobler
  • 41
  • 1
  • 4
  • DateTime.Now is purely functional, in that it has no side-effects (the fact that it takes time to execute might conceivably be called a side-effect, but since execution time--at least when bounded and short--is not considered a side-effect of any other method, I wouldn't consider it to be one here either). – supercat Oct 30 '12 at 19:14
  • 2
    Hi supercat. You are correct about externally observable side effects preventing a function from being pure, but the other constraint is that a pure function result value must *only* depend on the parameters. A pure static property, as a function, must therefore be both immutable and constant. A sophisticated compiler can replace all subsequent calls to a pure function with no parameters with the result returned by the first call. – T.Tobler Jan 10 '13 at 02:13
  • You're correct that my terminology was imprecise, but I think appropriateness of something being a read-only property rather than a method is dependent upon a lack of side-effects, rather than purity. – supercat Jan 10 '13 at 02:53
4

You could perhaps go around the problem by creating a new property:

public new int Bar 
{            
    get { return 0; }
    set {}        
}

int IBase.Bar { 
  get { return Bar; }
}
Hallgrim
  • 15,143
  • 10
  • 46
  • 54
  • 5
    But you can do this only when implementing an interface, not when inheriting from a base class. You'd have to choose another name. – svick May 05 '11 at 16:06
  • I assume example class implements IBase (something like public interface IBase { int Bar { get; } }), otherwise in implementing class, int IBase.Bar {...} is not allowed. Then you can simply create a regular property Bar with both get and set, eventho the Bar property from the interface does not require a set. – Ibrahim ben Salah Jan 11 '15 at 23:21
2

I can understand all your points, but effectively, C# 3.0's automatic properties get useless in that case.

You can't do anything like that:

public class ConcreteClass : BaseClass
{
    public override int Bar
    {
        get;
        private set;
    }
}

IMO, C# should not restrict such scenarios. It's the responsibility of the developer to use it accordingly.

Thomas Danecker
  • 4,635
  • 4
  • 32
  • 31
  • 1
    I don't understand your point. Do you concur that C# should allow adding a setter, or are you with most of the other people that answered this question? – ripper234 Sep 20 '08 at 15:21
  • 2
    As I said, IMO, C# should allow adding a setter. It's the responsibility of the developer to use it accordingly. – Thomas Danecker Sep 23 '08 at 15:13
  • Having a private setter like this **should** indeed be possible. I consider this a bug. – l33t Aug 31 '22 at 14:03
1

The problem is that for whatever reason Microsoft decided that there should be three distinct types of properties: read-only, write-only, and read-write, only one of which may exist with a given signature in a given context; properties may only be overridden by identically-declared properties. To do what you want it would be necessary to create two properties with the same name and signature--one of which was read-only, and one of which was read-write.

Personally, I wish that the whole concept of "properties" could be abolished, except that property-ish syntax could be used as syntactic sugar to call "get" and "set" methods. This would not only facilitate the 'add set' option, but would also allow for 'get' to return a different type from 'set'. While such an ability wouldn't be used terribly often, it could sometimes be useful to have a 'get' method return a wrapper object while the 'set' could accept either a wrapper or actual data.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

Here is a work-around in order to achieve this using Reflection:

var UpdatedGiftItem = // object value to update;

foreach (var proInfo in UpdatedGiftItem.GetType().GetProperties())
{
    var updatedValue = proInfo.GetValue(UpdatedGiftItem, null);
    var targetpropInfo = this.GiftItem.GetType().GetProperty(proInfo.Name);
    targetpropInfo.SetValue(this.GiftItem, updatedValue,null);
}

This way we can set object value on a property that is readonly. Might not work in all the scenarios though!

  • 2
    Are you sure you can call a setter via reflection that does not exist (as happens in the described getter-only properties)? – O. R. Mapper Sep 29 '13 at 15:15
0

You should alter your question title to either detail that your question is solely in regards to overriding an abstract property, or that your question is in regards to generally overriding a class's get-only property.


If the former (overriding an abstract property)

That code is useless. A base class alone shouldn't tell you that you're forced to override a Get-Only property (Perhaps an Interface). A base class provides common functionality which may require specific input from an implementing class. Therefore, the common functionality may make calls to abstract properties or methods. In the given case, the common functionality methods should be asking for you to override an abstract method such as:

public int GetBar(){}

But if you have no control over that, and the functionality of the base class reads from its own public property (weird), then just do this:

public abstract class BaseClass
{
    public abstract int Bar { get; }
}

public class ConcreteClass : BaseClass
{
    private int _bar;
    public override int Bar
    {
        get { return _bar; }
    }
    public void SetBar(int value)
    {
        _bar = value;
    }
}

I want to point out the (weird) comment: I would say a best-practice is for a class to not use its own public properties, but to use its private/protected fields when they exist. So this is a better pattern:

public abstract class BaseClass {
    protected int _bar;
    public int Bar { get { return _bar; } }
    protected void DoBaseStuff()
    {
        SetBar();
        //Do something with _bar;
    }
    protected abstract void SetBar();
}

public class ConcreteClass : BaseClass {
    protected override void SetBar() { _bar = 5; }
}

If the latter (overriding a class's get-only property)

Every non-abstract property has a setter. Otherwise it's useless and you shouldn't care to use it. Microsoft doesn't have to allow you to do what you want. Reason being: the setter exists in some form or another, and you can accomplish what you want Veerryy easily.

The base class, or any class where you can read a property with {get;}, has SOME sort of exposed setter for that property. The metadata will look like this:

public abstract class BaseClass
{
    public int Bar { get; }
}

But the implementation will have two ends of the spectrum of complexity:

Least Complex:

public abstract class BaseClass
{
    private int _bar;
    public int Bar { 
        get{
            return _bar;
        }}
    public void SetBar(int value) { _bar = value; }
}

Most Complex:

public abstract class BaseClass
{
    private int _foo;
    private int _baz;
    private int _wtf;
    private int _kthx;
    private int _lawl;

    public int Bar
    {
        get { return _foo * _baz + _kthx; }
    }
    public bool TryDoSomethingBaz(MyEnum whatever, int input)
    {
        switch (whatever)
        {
            case MyEnum.lol:
                _baz = _lawl + input;
                return true;
            case MyEnum.wtf:
                _baz = _wtf * input;
                break;
        }
        return false;
    }
    public void TryBlowThingsUp(DateTime when)
    {
        //Some Crazy Madeup Code
        _kthx = DaysSinceEaster(when);
    }
    public int DaysSinceEaster(DateTime when)
    {
        return 2; //<-- calculations
    }
}
public enum MyEnum
{
    lol,
    wtf,
}

My point being, either way, you have the setter exposed. In your case, you may want to override int Bar because you don't want the base class to handle it, don't have access to review how it's handling it, or were tasked to hax some code real quick'n'dirty against your will.

In both Latter and Former (Conclusion)

Long-Story Short: It isn't necessary for Microsoft to change anything. You can choose how your implementing class is set up and, sans the constructor, use all or none of the base class.

Suamere
  • 5,691
  • 2
  • 44
  • 58
0

Solution for only a small subset of use cases, but nevertheless: in C# 6.0 "readonly" setter is automatically added for overridden getter-only properties.

public abstract class BaseClass
{
    public abstract int Bar { get; }
}

public class ConcreteClass : BaseClass
{
    public override int Bar { get; }

    public ConcreteClass(int bar)
    {
        Bar = bar;
    }
}
lxa
  • 3,234
  • 2
  • 30
  • 31
-1

This is not impossible. You simply have to use the "new" keyword in your property. For example,

namespace {
    public class Base {
        private int _baseProperty = 0;

        public virtual int BaseProperty {
            get {
                return _baseProperty;
            }
        }

    }

    public class Test : Base {
        private int _testBaseProperty = 5;

        public new int BaseProperty {
            get {
                return _testBaseProperty;
            }
            set {
                _testBaseProperty = value;
            }
        }
    }
}

It appears as if this approach satisfies both sides of this discussion. Using "new" breaks the contract between the base class implementation and the subclass implementation. This is necessary when a Class can have multiple contracts (either via interface or base class).

Hope this helps

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
mbolt35
  • 131
  • 2
  • 5
  • 30
    This answer is wrong because the property marked `new` no longer overrides the virtual base one. In particular, if the base property is *abstract*, as it is in the original post, it is impossible to use the `new` keyword in a non-abstract subclass because you have to override all abstract members. – Timwi Apr 09 '11 at 13:12
  • This is phenomenally dangerous because the following return different results despite being the same object: `Test t = new Test(); Base b = t; Console.WriteLine(t.BaseProperty)` gives you 5, `Console.WriteLine(b.BaseProperty)` gives you 0, and when your successor has to debug this you'd better have moved far, far away. – Mark Sowul Jun 18 '14 at 14:26
  • I agree w/ Mark, this is extremely nasty. If both BaseProperty implementations were backed by the same variable it would be fine though IMHO. IE: Make _baseProperty protected and abolish _testBaseProperty. Also, AFAIK the implementation in Base does not need to be virtual since you're not actually overriding it. – Steazy Oct 23 '14 at 20:48
  • Most answers to questions can have valid opinion and input. But apart from the previous comments, my main criticism on this answer is that I believe the actual question may be literally about abstract properties in a codebase that the consumer has no control over. So my criticism is that this answer may not fit the question. – Suamere Oct 22 '15 at 20:25
-2

Because that would break the concept of encapsulation and implementation hiding. Consider the case when you create a class, ship it, and then the consumer of your class makes himself able to set a property for which you originally provide a getter only. It would effectively disrupt any invariants of your class which you can depend on in your implementation.

petr k.
  • 8,040
  • 7
  • 41
  • 52
  • 4
    -1: Having a setter does not automatically enable a descendant to break any invariants. The setter can still only change things that are already changeable by the descendant anyway. – Roman Starkov Apr 09 '11 at 13:07
  • @RomanStarkov That's true. But the question of this post is; Why can't can't add a setter to an abstraction who contracts you not to. Your comment would be appropriate in the opposite question; *Why does Microsoft allow you to create a ReadOnly property in an abstraction if the descendant has full control of its private fields anyway?* – Suamere Mar 17 '17 at 14:13
  • +1: This question is about why Microsoft doesn't allow you to break a contract. Though the reason for your downvotes is more about why Microsoft allows a contract to include readonly properties only. So this answer is correct in the context. – Suamere Mar 17 '17 at 14:14
  • 2
    @Suamere the contract doesn't state that the property cannot be changed. All that it states is that there exists a property that can be read. Adding a setter will not break this contract. You can _interpret_ it as an _intention_ to create a read-only property, but you cannot guarantee in C# 6 that there's no way to change it, hence the contract you're thinking of isn't actually there. Think about an interface: it can offer a contract on a gettable (not get-only!) property. This interface can be implemented by a get+set property just fine. – Roman Starkov Mar 17 '17 at 18:58
  • You are approaching this from the perspective of the concrete author. He can change it as he pleases. I am approaching it from the perspective of the base class author -> Approaching as the end result consumer of the implementing class. The author of the base class doesn't want any consumer of the future concrete classes to be able to change that property without the author of the concrete class exposing a special method to handle case-by-case basis. Because in the base class, that property is treated as immutable, and that is communicated by only exposing it as such. – Suamere Mar 20 '17 at 15:58
-3

A read-only property in the base class indicates that this property represents a value that can always be determined from within the class (for example an enum value matching the (db-)context of an object). So the responsibillity of determining the value stays within the class.

Adding a setter would cause an awkward issue here: A validation error should occur if you set the value to anything else than the single possible value it already has.

Rules often have exceptions, though. It is very well possible that for example in one derived class the context narrows the possible enum values down to 3 out of 10, yet the user of this object still needs to decide which one is correct. The derived class needs to delegate the responsibillity of determining the value to the user of this object. Important to realize is that the user of this object should be well aware of this exception and assume the responsibillity to set the correct value.

My solution in these kind of situations would be to leave the property read-only and add a new read-write property to the derived class to support the exception. The override of the original property will simply return the value of the new property. The new property can have a proper name indicating the context of this exception properly.

This also supports the valid remark: "make it as hard as possible for misunderstandings to crop up" by Gishu.

Remco te Wierik
  • 1,436
  • 2
  • 10
  • 10
  • 3
    No awkwardness would be implied by a `ReadableMatrix` class (with a two-argument read-only indexed property) having subtypes `ImmutableMatrix` and `MutableMatrix`. Code which only needs to read a matrix, and doesn't care if it might change some time in future, could accept a parameter of type `ReadableMatrix` and be perfectly happy with mutable or immutable subtypes. – supercat Oct 30 '12 at 19:28
  • An additional setter could modify a private variable within the class. The so-called "read-only" property from the base class would then still determine the value "from within the class" (by reading the new private variable). I don't see the issue there. Also look at, for example, what [`List.Count`](http://msdn.microsoft.com/en-us/library/27b47ht3.aspx) does: It cannot be assigned to, but that does not mean it is "read-only" in that it cannot be modified by users of the class. It can very well be modified, albeit indirectly, by adding and removing list items. – O. R. Mapper Sep 29 '13 at 15:13
-3

Because a class that has a read-only property (no setter) probably has a good reason for it. There might not be any underlying datastore, for example. Allowing you to create a setter breaks the contract set forth by the class. It's just bad OOP.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Up-Vote. This is very succinct. Why should Microsoft allow the consumer of a base class to break the contract? I agree with this very short version of my too-long-and-confusing answer. Lol. If you're a consumer of a base class, you shouldn't want to break the contract, but you CAN implement it in a couple different ways. – Suamere Mar 17 '17 at 14:09
-4

Because at the IL level, a read/write property translates into two (getter and setter) methods.

When overriding, you have to keep supporting the underlying interface. If you could add a setter, you would effectively be adding a new method, which would remain invisible to the outside world, as far as your classes' interface was concerned.

True, adding a new method would not be breaking compatibility per se, but since it would remain hidden, decision to disallow this makes perfect sense.

Ishmaeel
  • 14,138
  • 9
  • 71
  • 83
  • 3
    I don't care much about "the outside world" here. I want to add functionality to a class, which is always visible only to code that knows the specific class and not the base. – ripper234 Sep 17 '08 at 15:13
  • @ripper234 See Matt bolt's answer: if you want to make the new property visible only to users of the derived class you should use `new` instead of `override`. – Dan Berindei Dec 02 '10 at 09:21
  • 1
    It does not remain hidden. You're like saying you can't add a new method to a child-class because the new method will be "remain hidden from the outside world". Of course it's remain hidden from base-class perspective, but it's accessible from the clients of the child class. (I.e. to affect what the getter should return) – Sheepy Aug 17 '11 at 03:46
  • Sheepy, that's not what I'm saying at all. I mean, exactly as you pointed out, it would remain hidden "from a base-class perspective". That's why I appended "as far as your classes' _interface_ was concerned". If you are subclassing a base class, it is almost certain that the "outside world" will be referring to your object instances with the base class type. If they would directly use your concrete class, you would not need compatibility with the base class and you could, by all means, use `new` with your additions. – Ishmaeel Aug 17 '11 at 10:13
-8

Because the writer of Baseclass has explicitly declared that Bar has to be a read-only property. It doesn't make sense for derivations to break this contract and make it read-write.

I'm with Microsoft on this one.
Let's say I'm a new programmer who has been told to code against the Baseclass derivation. i write something that assumes that Bar cannot be written to (since the Baseclass explicitly states that it is a get only property). Now with your derivation, my code may break. e.g.

public class BarProvider
{ BaseClass _source;
  Bar _currentBar;

  public void setSource(BaseClass b)
  {
    _source = b;
    _currentBar = b.Bar;
  }

  public Bar getBar()
  { return _currentBar;  }
}

Since Bar cannot be set as per the BaseClass interface, BarProvider assumes that caching is a safe thing to do - Since Bar cannot be modified. But if set was possible in a derivation, this class could be serving stale values if someone modified the _source object's Bar property externally. The point being 'Be Open, avoid doing sneaky things and surprising people'

Update: Ilya Ryzhenkov asks 'Why don't interfaces play by the same rules then?' Hmm.. this gets muddier as I think about it.
An interface is a contract that says 'expect an implementation to have a read property named Bar.' Personally I'm much less likely to make that assumption of read-only if I saw an Interface. When i see a get-only property on an interface, I read it as 'Any implementation would expose this attribute Bar'... on a base-class it clicks as 'Bar is a read-only property'. Of course technically you're not breaking the contract.. you're doing more. So you're right in a sense.. I'd close by saying 'make it as hard as possible for misunderstandings to crop up'.

Gishu
  • 134,492
  • 47
  • 225
  • 308
  • 97
    I am still not convinced. Even if there is no explicit setter, this doesn't guarantee that the property will always return the same object - it can still be changed by some other method. – ripper234 Sep 17 '08 at 15:12
  • Updated with an example.. HTH – Gishu Sep 18 '08 at 04:05
  • 35
    Shouldn't the same be true for interfaces, then? You can have readonly property on interface and read/write on implementing type. – Ilya Ryzhenkov Sep 19 '08 at 18:52
  • 2
    Nice question... feeble attempt at answering it above :) – Gishu Sep 20 '08 at 06:26
  • 1
    @Ilya. No the same doesn't neccesarilly follow for interfaces as they are effectively "view" into the implementing type. So an interface will always expose either the same or fewer members than are part of the implementing type. – Shaun Austin Sep 20 '08 at 09:18
  • 52
    I disagree: the base class only declared the property as having no setter; that is not the same as the property being read-only. "Read-only" is only a meaning *you* assign to it. There are no relevant guarantees built into C# at all. You could have a get-only property that changes every time, or a get/set property where the setter throws an `InvalidOperationException("This instance is read-only")`. – Roman Starkov Apr 03 '10 at 13:09
  • 1
    @Ilya try casting your type to the specific interface and you'll find that you won't have any setter anymore since that haven't been explicitly defined in the interface. – Pauli Østerø Jan 06 '11 at 04:20
  • 2
    @Pauli Østerø: how's that a problem? The method/setter is not visible from the interface/base-class perspective because it doesnt belong there. In the other hand, you should be able to declare additional methods (and setters) on your child classes, and there are a lot of very legitimate reasons for it. Especially if the getter property is defined as an abstract. – Sheepy Aug 17 '11 at 03:50
  • 25
    Looking at getters and setters as methods, I don't see why it should be a "breach of contract" any more than adding a new method. A base-class contract has nothing to do with what functionality is *not* present, only with what *is* present. – Dave Cousineau Jun 27 '12 at 01:12
  • 41
    -1 I disagree with this answer, and find it misguiding. Since a base class defines the behaviour that any class must abide to (See Liskov's Substitution Principle), but does not (and should not) restrict to add behaviour. A base class may only define what the behaviour must be, and it cannot (and should not) specify what the behaviour 'must not be' (i.e. 'must not be writable at concrete levels)'. – Marcel Valdez Orozco Mar 16 '13 at 22:16
  • 2
    Yes - if you want to prevent a subclass from adding to the contract (such as adding data mutation behavior), you must simply seal your base class. No other way. (You can prevent subclass from mutating your existing fields - by making those private - but you can't prevent it from defining new behaviour). – Iain Nov 21 '13 at 00:25
  • I don't agree with MS. It should have at least a possibility like "private new set;" like shadowing normal methods. Hence a property just generates get_ and set_ methods eventually. – Ray Aug 24 '14 at 17:11
  • 1
    I also disagree with the "contract breaking" argument. IMHO properties are in many ways sementically just syntax sugar for Java-style getter/setter pairs (yes, I know that technically they are more than that in the CLR, but that's mostly just an implementation detail). In Java, adding a setter that wasn't declared in the base class wouldn't break any contract either. Also, as has already been pointed out, the contract argument doesn't adequately explain why interfaces behave more relaxed here. Personally, I think it simply was easier to implement this way for Microsoft. – chris Aug 26 '14 at 12:12
  • 2
    I disagree with the Answer, because in general the interface describes what you CAN do instead of what you CAN'T (see also explanation of Marcel Valdez). e.g when implementing an interface property containing only get accessor, then you may add additional set accessor (or vice versa). The strange (frustrating) fact is, this does not apply to abstract properties and sub-interfaces overriding properties from base interfaces. I believe this is just a limitation of the syntax. – Ibrahim ben Salah Jan 11 '15 at 23:32
  • 1
    Base class is only a view. It is *very* common for objects to be mutable without allowing the user to mutate them. For instance, it might be getting data from somewhere and it makes no sense for the consumer to write to it but the consumer expects the property to change. This is identical to the argument when people claim that `IReadOnlyList` should be used to imply immutability even though `List` implements it. Even [`IImmutableList`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable.iimmutablelist-1?view=netcore-2.0) doesn’t guarantee immutability. – binki Dec 28 '17 at 15:18
  • @Marcel That's really not a fair use of a -1. I think where your arg goes astray is thinking of a property as a getter & setter method, when in this case it has to just be thought of as an atomic class member. Nothing's stopping a derived class from defining a setter _method_. But they decided the base class gets to dictate a property's "signature". The base class is not defining what a derived class can't be/do, but it does get to control what it defines. It gives you some power as the base class writer. It may have been more flexible to allow a base class to explicitly declare "no setter". – xr280xr Sep 13 '19 at 20:43
  • I find it amusing that this answer has so many upvotes and at the same time so many downvotes. This must be a stackoverflow-wide record-setter. I have to say I am sorry for contributing to bringing the net sum down to zero. People have done this to me in the past, downvoting as a matter of opinion, and it is indeed frustrating. This helps better than anything else to illustrate why stackoverflow discourages q&as which are subject to opinion. – Mike Nakis Oct 22 '19 at 14:27