0

Say I have a property like this in an abstract class AbstractClass:

protected MyClass MyProperty { get; set; }

And this property is used in a number of (virtual) methods in AbstractClass. In a subclass of the AbstractClass I want MyProperty to be a subclass of MyClass, is this possible or do I have to cast it?

MyProperty = new SubclassOfMyClass();
((SubclassOfMyClass)MyProperty).Method();

Doesn't look very nice... I have tried to use the 'new' keyword to hide MyProperty like this:

protected new SubclassOfMyClass MyProperty { get; set; }

But this did not work out as I thought it would, as it seems to creates a second MyProperty, and results in the one in AbstractClass always being null.

So I came up with something that may seem like a bit of a hack:

protected new SubclassOfMyClass MyProperty 
{
    get { return base.MyProperty as SubclassOfMyClass; }
    set { base.MyProperty = value; }
}

Is there a better way to do this?

moggizx
  • 476
  • 1
  • 5
  • 19
  • You can use generics. Check this answer: http://stackoverflow.com/a/1048902/393487 – Ahmed KRAIEM Oct 11 '13 at 08:37
  • 1
    On the "is this possible part", have a look at http://stackoverflow.com/a/4349584/1236044 I guess you won't find a better explanation – jbl Oct 11 '13 at 08:42

1 Answers1

0

You can use generics:

public abstract class AbstractClass<T> where T : MyClass, new() {
    protected T MyProperty { get; set; }
}

public class SubClass : AbstractClass<SubclassOfMyClass> {
}

EDIT:

This is in response to your "hack":

Consider this code:

public class MyClass { }
public class SubclassOfMyClass : MyClass { }

public abstract class AbstractClass
{
    public MyClass MyProperty { get; set; }
}

public class Subclass : AbstractClass
{
    public new SubclassOfMyClass MyProperty
    {
        get { return base.MyProperty as SubclassOfMyClass; }
        set { base.MyProperty = value; }
    }
}

public class Test
{
    public static void Main()
    {
        AbstractClass sub = new Subclass();
        sub.MyProperty = new MyClass();

        Subclass sub2 = (Subclass)sub;//casting succeeds since sub is Subclass 
        if (sub2.MyProperty == null)
            Console.WriteLine("sub2.MyProperty is null!");
    }
}

This actually prints "sub2.MyProperty is null!". After casting sub to sub2 and then accessing sub2.MyProperty base.MyProperty is still of type MyClass and base.MyProperty as SubclassOfMyClass returns null as expected. So if you're going to use the new keyword you should really know what's going on behind the scenes.

Ahmed KRAIEM
  • 10,267
  • 4
  • 30
  • 33
  • Oh, stupid of me to not think of the fact that you can define the generic type in the class declaration... I did think of generics but I didn't want to create mappings to SubclassOfMyClass for each subclass of AbstractClass. – moggizx Oct 11 '13 at 08:47
  • By the way, what exactly does "new()" imply here? – moggizx Oct 11 '13 at 08:53
  • 1
    [The new constraint specifies that any type argument in a generic class declaration must have a public parameterless constructor. To use the new constraint, the type cannot be abstract.](http://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx) – Ahmed KRAIEM Oct 11 '13 at 08:57
  • I see. I decided to go with my "hack" anyway because firstly; I did not want to have to declare all references of AbstractClass as AbstractClass (I have quite a lot of references to this class, it could be considered the "core" class of my program), and secondly; the type of MyProperty is not of any interest to any outside class anyway. – moggizx Oct 11 '13 at 09:15
  • Yes, I realize this but it's fine since MyProperty is protected in my case, not public. The only way this could happen would be if AbstractClass or Subclass would cast itself to AbstractClass, which seems like a pretty slim scenario... – moggizx Oct 11 '13 at 11:03
  • Unless I'm missing something? – moggizx Oct 11 '13 at 11:05