Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# inheritance of fields

Tags:

c#

inheritance

This is probably a silly question, but here it goes.Imagine you have the following classes:

public class C
{
}

public class D : C
{
     //A subclass of C
}

public class A
{
    C argument;     
}

Now, I want to have a class B, that inherits from A.This class would obviously inherit the "argument" field, but I wish to force the "argument" field in B to be of type D, rather than C.Since D inherits from C this shouldn't create any problems. So, how would achieve this in c# ?

like image 816
Emil D Avatar asked Dec 03 '22 13:12

Emil D


2 Answers

As Jared points out, this is not possible. However, it is interesting to consider why not.

Suppose the field is private. Then it cannot be accessed in derived class B. (Assuming B is not a nested type of A.)

Suppose the field is not private. Doesn't matter whether it is public, internal, protected or protected internal. Suppose its public and this were legal. Now you have the following situation.

class B : A 
{
    override public D argument; // "overrides" A.argument
}

class E : C {  }

class F
{
    public static void M(A a)
    { a.argument = new E(); }
}

... 
F.M(new B());

And hey, you just crashed the runtime. You just wrote an object of type E into a field that can only store type D. (We could make similar crashing scenarios for other configurations, like protected fields, and so on.)

Now, you might say, well, instead let me make a read-only property. That I can virtualize:

class A 
{
    public virtual C Argument { get; }
}
class B : A
{
    public override D Argument { ... }
}

Now the problems go away. The public interface isn't writable, so there's no problem with someone writing something in there that is not supported. And the property is virtual, so there's a mechanism for overriding it.

That feature is called "return type covariance", and it is not supported in C# either. See Why the concept of "Covariance" and "Contravariance" are applicable while implementing the methods of an interface?.

Please explain what you are really trying to do, not how you're trying to do it. There is probably a better way.

like image 120
Eric Lippert Avatar answered Dec 22 '22 22:12

Eric Lippert


You could achieve something like so, where A is a generic type with its type parameter constrained to subclasses of C:-

public class C
{
}

public class D : C
{
}

public class A<T> where T:C
{
    public T Argument { get; set; }
}

public class B : A<D>
{
}

Bear in mind that you shouldn't expose public (or protected) fields, which is why I've changed them to properties.

like image 29
Adam Ralph Avatar answered Dec 22 '22 20:12

Adam Ralph