I have the following code.
class Header<T> where T: IItem { }
class HeaderA : Header<ItemA> { }
class HeaderB : Header<ItemB> { }
interface IItem { }
class ItemA : IItem { }
class ItemB : IItem { }
Header<IItem> h = new HeaderA();
The last line cannot be compiled.
Cannot implicitly convert type 'UserQuery.HeaderA' to 'UserQuery.Header<UserQuery.IItem>'
HeaderA is a subtype of Header and ItemA is a subtype of IItem. Why it doesn't work?
In short, you're trying to use a concept called covariance, which is not supported in .NET generic classes, and not supported by default in interfaces.
If you want to allow the class to do this, you can specify it in C# 3 or later using the
out
contextual keyword on a generic interface:By using the interface with the keyword, you are basically telling the compiler that no usage of the interface will ever have to know more about the generic type than that it meets the constraints of the interface's generic type declaration (or that it's an object). As such, while you can now assign more derived generics to variables of the interface type, you can only deal with them as the interface type, never as any derived type.
The
out
keyword is not acceptable for class definitions; you cannot force usages ofHeader<T>
to be covariant.