Reputation: 3328
I don't see what is wrong with the following code, or how I can fix it. (Maybe I am misunderstanding generic types.)
class X<I>
where I : ISomeInterface
{ }
class Y<T>
where T : X<ISomeInterface>
{ }
class Z<I>
where I : ISomeInterface
{
Y<X<I>> AData { get; } // What compiler does not like
Y<X<ISomeInterface>> BData { get; } // What compiler likes
}
Compiler complains that it cannot use X<I>
as type parameter T
in the generic type Y<T>
.
Upvotes: 2
Views: 2133
Reputation: 9009
Here is a working solution
interface ISomeInterface {}
class X<I>
where I : ISomeInterface
{ }
class Y<T, I>
where T : X<I>
where I : ISomeInterface
{ }
class Z<I>
where I : ISomeInterface
{
Y<X<I>, I> MyOtherData { get; set; }
Y<X<ISomeInterface>, ISomeInterface> MyData { get; set; }
}
Notice the additional generic parameter I
and constraints I have added to the definition of type Y
.
Your initial definition of Y
is too restrictive. C# makes a difference between ISomeInterface
and any type implementing ISomeInterface
.
Why is it so ?
The .NET compiler has a special way of handing generic types. For each generic type the compiler will create a separate type based on the generic type arguments, which is instead used during runtime. For example List<int>
and List<string>
will be completely different types, all exhibiting the behaviours defined by the List<_>
generic type, but with the actual type int
or string
baked into the concrete type generated by the compiler.
When you define class Y<T> where T : X<ISomeInterface>
you "seal" the generic parameter of X
to be ISomeInterface
. The compiler will accept any type inheriting X<ISomeInterface>
but not X<SomethingElse>
even if SomethingElse
is itself an implementation of ISomeInterface
. This is because the fragment where T : X<ISomeInterface>
causes the ISomeInterface
to be "baked in" within the type definition of Y<T>
. That behaviour is expected and is a side effect of how generics are compiled to actual code. For the same reason one cannot do the following:
List<object> x = new List<string>();
even though the type string
inherits from object
.
Upvotes: 4