0

So I have a container type generic object I'm using that looks like this:

public class Property<T>
{
    T Value { get; set; }
}

I want to be able to do lists of Property of different generic types, so I did this:

public class Property
{
    object BaseValue { get; set; }
}
public class Property<T> : Property
{
    T Value { get; set; }
}

List<Property> properties = new List<Property>();

(Not shown is that BaseValue and Value both point to the same object, they'll always be the same). So now I can have collections of different types of properties. The problem I have now involves inheritance constraints. Say I have the following classes:

public abstract class Base { }
public class A : Base { }
public class B : Base { }
public class C { }

I want to be able to have a generic typed Property class that constrains the type that goes in it, and that can be used as a generic parameter to other generics. Basically:

public List<Property<Base>> baseList = new List<Property<Base>>();
baseList.Add(new Property<A>()) //Works
baseList.Add(new Property<B>()) //Works
baseList.Add(new Property<C>()) //Won't work

However this doesn't work because even though A inherits from Base, Property<A> does not inherit from Property<Base>.

Is there some way to restructure these classes to allow that type of restraint? My current thought is making a new class something like:

public class PropertyBase<T> : Property<T> where T : Base { }

And using that, but 1) I'm not sure it would work, and 2) Even if it does, it would also create multiple classes that are functionally identical, but different types (Property<A> and PropertyBase<A> are pretty much the same functionally, but different types).

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
Card
  • 53
  • 5
  • _"Is there some way to restructure these classes to allow that type of restraint?"_ -- no. And you wouldn't want there to be. See marked duplicate for details. The short version is that the relationship you are trying to express _is not safe_. So the language doesn't let you do it. – Peter Duniho Mar 03 '17 at 00:52
  • See also e.g. https://stackoverflow.com/questions/3117411/why-does-the-following-doesnt-compile-involves-generics-and-inheritance-in-c and https://stackoverflow.com/questions/7444166/why-can-i-not-convert-a-foobar-to-ifooibar. The latter includes a hint as to how you could get it to work if a) you can express the types as interfaces, and b) the types have suitable functionality so that what you want _is_ safe (i.e. you can declare the type parameters with `out`). – Peter Duniho Mar 03 '17 at 00:52
  • For a much more in-depth discussion of the topic, you may also be interested in https://stackoverflow.com/questions/17231577/what-are-the-kinds-of-covariance-in-c-or-covariance-by-example – Peter Duniho Mar 03 '17 at 00:52
  • Thanks for the links. I'd seen some of them previously, but moreso I was wondering if my scenario was fixable with any design pattern, even if it meant shying away from Generics. After reading the links it looks like I can't have everything I want, so I'll just settle with not having the compile-time constraint. Thanks! – Card Mar 03 '17 at 02:22

0 Answers0