Can I Override with derived types?
You can re-declare (new), but you can't re-declare and override at the same time (with the same name). One option is to use a protected method to hide the detail - this allows both polymorphism and hiding at the same time:
public class Father
{
public Father SomePropertyName
{
get {
return SomePropertyImpl();
}
}
protected virtual Father SomePropertyImpl()
{
// base-class version
}
}
public class Child : Father
{
public new Child SomePropertyName
{
get
{ // since we know our local SomePropertyImpl actually returns a Child
return (Child)SomePropertyImpl();
}
}
protected override Father SomePropertyImpl()
{
// do something different, might return a Child
// but typed as Father for the return
}
}
This is not possible in any .NET language because of type-safety concerns. In type-safe languages, you must provide covariance for return values, and contravariance for parameters. Take this code:
class B {
S Get();
Set(S);
}
class D : B {
T Get();
Set(T);
}
For the Get
methods, covariance means that T
must either be S
or a type derived from S
. Otherwise, if you had a reference to an object of type D
stored in a variable typed B
, when you called B.Get()
you wouldn't get an object representable as an S
back -- breaking the type system.
For the Set
methods, contravariance means that T
must either be S
or a type that S
derives from. Otherwise, if you had a reference to an object of type D
stored in a variable typed B
, when you called B.Set(X)
, where X
was of type S
but not of type T
, D::Set(T)
would get an object of a type it did not expect.
In C#, there was a conscious decision to disallow changing the type when overloading properties, even when they have only one of the getter/setter pair, because it would otherwise have very inconsistent behavior ("You mean, I can change the type on the one with a getter, but not one with both a getter and setter? Why not?!?" -- Anonymous Alternate Universe Newbie).