0

Effectively, I'd like to understand why this is not possible in C#:

class Foo{
    public Bar Property {get;set;}
}

class Boo : Foo{
    public override Baz Property {get;set;}
}

class Bar{
    //some internal stuff
}

class Baz : Bar{
    //more stuff
}

To me, it seems like this would have pretty clearly defined behavior in most cases, so long as the Baz class doesn't hide a member from the Bar class (with new or something). The compiler would know if this was going to happen though, so it seems like a kind of non-issue.

I also understand that this can be achieved with abstract classes, but I specifically would like to get a better understanding of why this is disallowed in the case of non-abstract classes.

Nimantha
  • 6,405
  • 6
  • 28
  • 69

2 Answers2

4

Imagine someone uses your code:

Foo f = new Boo();

As the reference is of type Foo we can only assume Property to be of type Bar. So we can also write this now:

f.Property = new Boz(); // assuming Boz also derives from Bar

which will pretty sure not be what you actually wanted.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • Yeah thanks that makes sense. I can't help but think there should be some way around it, in terms of compiler errors or something, but thanks! – PhonicCanine Aug 27 '20 at 08:36
2

You can use the following workaround for that, but making Foo generic interface and implement it in Boo class

interface IFoo<T> where T : Bar
{
    public T Property { get; set; }
}

class Boo : IFoo<Baz>
{
    public Baz Property { get; set; }
}

There is also a covariant return types, planned in C# 9. But it'll work with readonly properties only

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66