Generics, inheritance and casting

My question is related to foundry classes within a generic type. Although I understand that cast objects, such as List<string> to List<object> , require covariance support to prevent adding object object to a list containing strings, I wonder why the compiler cast is not accepted as a listing like below, and whether it is solvable using interfaces and covariance or contravariance:

 public class TypeA<T> {} public class TypeB<T> {} public class TypeC : TypeB<int> {} class Program { public static void MyMethod<OutputType>(TypeA<TypeB<OutputType>> Parameter) {} static void Main(string[] args) { TypeA<TypeC> Test = new TypeA<TypeC>(); MyMethod<int>(Test); } } 

Compiling the results results in an error:

Argument 1: cannot convert from 'ConsoleApplication1.TypeA<ConsoleApplication1.TypeC>' to 'ConsoleApplication1.TypeA<ConsoleApplication1.TypeB<int>>' .

although TypeC is a direct descendant of TypeB<int>

+4
source share
6 answers

Well, since C # 4.0 supports covariance for generics interfaces, the following example may solve the problem:

 public interface ITypeA<out T> {} public class TypeA<T> : ITypeA<T> {} public class TypeB<T> {} public class TypeC : TypeB<int> {} class Program { public static void MyMethod<OutputType>(ITypeA<TypeB<OutputType>> Parameter) {} static void Main(string[] args) { ITypeA<TypeC> Test = new TypeA<TypeC>(); MyMethod<int>(Test); } } 

Note that type T can only be used for return values ​​from methods in ITypeA.

+2
source

As other commentators noted, even though TypeC derived from TypeB<int> , it is not true that TypeA<TypeC> comes from TypeA<TypeB<int>> . However, you can probably make your code work by adding an additional type parameter to MyMethod :

 public static void MyMethod<DerivedB,OutputType>(TypeA<DerivedB> Parameter) where DerivedB : TypeB<OutputType> {} 
+3
source

I am rather confused by your question, since the preamble of the question shows that you know what the answer is. You cannot convert List<string> to List<object> , because then you can add Giraffe to the list of objects, which is actually a list of strings, which is not typical.

If you replace "TypeA" with "List", TypeB<int> with "object" and "TypeC" with "string", then you have turned your situation into one that you already know does not work for good reasons. This does not mean that the compiler magically knows something about List and simply does not allow the List script - rather, the compiler does not allow such dispersion.

In C # 4, we add deviations regarding any interface and delegate types that are known to be typical in variance. This is the "choose" model - you need to prove that you are safe, and only then we will allow you to use the variance.

+3
source

Another generic covariance problem - see the answer I posted here . TypeA <TypeC> does not inherit TypeA <TypeB <int> gt; anyway

+2
source

But ConsoleApplication1.TypeA<ConsoleApplication1.TypeC> does not inherit from ConsoleApplication1.TypeA<ConsoleApplication1.TypeB<int>>

0
source

Say I have a List object. Then I listed it on the list. There is a method on the list called 'add' that takes a T argument. I am adding Apple to it (since I have a List). However, in some places my code still expects List, so some List members are actually apples !!!

So, TypeA cannot be distinguished from TypeA, even if X inherits from Y.

0
source

All Articles