5

I created the following abstract class:

public abstract class AbstractClass
{
    public abstract string Name { get; set; }
    public abstract object Value { get; set; }
}

Now I want to derive two classes of the abstract class. I want to use an enum instead of the type object. My derived classes look like this:

First class:

public class InheritanceClass1:AbstractClass
{
    public override string Name { get; set; }
    public override FirstEnum Value { get; set; }
}

Second class:

public class InheritanceClass2 : AbstractClass
{
    public override string Name { get; set; }
    public override SecondEnum Value { get; set; }
}

I'm getting an error showed in my code, that the type of the property Value isn't object. I tryed to use the new-keyword instead of override like this:

In my abstract class:

public object Value { get; set; }

In my derived class:

public new FirstEnum Value { get; set; }

But if I create a List<AbstractClass> I have the problem that I can't use it for example for Linq because I would retrieve the "wrong" property. It is just hided, but still there, so I have to override the property.

So how do I have to change my abstract class and my derived classes, that I can use different types in my derived classes?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
daniel59
  • 906
  • 2
  • 14
  • 31

1 Answers1

8

You can use abstract class like this:

public abstract class AbstractClass<T>
{
    public abstract string Name { get; set; }
    public abstract T Value { get; set; }
}

And derived class will change like this:

public class InheritanceClass1 : AbstractClass<FirstEnum>
{
    public override string Name { get; set; }
    public override FirstEnum Value { get; set; }
}

If you know that you will need only enums, you can add struct, IConvertible restriction to T:

public abstract class AbstractClass<T> where T : struct, IConvertible
{
    public abstract string Name { get; set; }
    public abstract T Value { get; set; }
}

Update based on comment:

Not the cleanest solution if you need List<AbstractClass>, but you can have additional class:

public abstract class AbstractClass
{
    public abstract string Name { get; set; }
    public abstract int GetValue ();
}

Which will then be inherited by AbstractClass<T>:

public abstract class AbstractClass<T> : AbstractClass where T : struct, IConvertible
{
    public abstract T Value { get; set; }
}

And InheritancClass:

public class InheritanceClass1 : AbstractClass<FirstEnum>
{
    public override string Name { get; set; }
    public override FirstEnum Value { get; set; }

    public override int GetValue () => (int)Value;
}

And then you can use it in a list:

var list = new List<AbstractClass> { new InheritanceClass1 (), new InheritanceClass2 () };

In this way you can use List<AbstractClass> with GetValue method. If you are using only enums you can always recast it to enum value. Ofcorse, you would not know exactly which enum it is, but you can add additional field for that.

Dovydas Šopa
  • 2,282
  • 8
  • 26
  • 34
  • 3
    But, of note is that you won't be able to have a `List` now. You can of course have a `List>` or a `List` but that's probably not why they had a `List` in the first place. – Damien_The_Unbeliever Feb 24 '16 at 08:30
  • 1
    var `list` contains just `null` values if I use your code. If I use the `enum` instead of `IConvertible` I get some values, but this would work just for one `enum` – daniel59 Feb 24 '16 at 09:15