Casting with a limited generic class in C #

Simply put, why is this code not compiled?

public interface IWorld { } public class Foo<T> where T : IWorld { } public void Hello<T>(T t) where T : IWorld { Foo<IWorld> bar1 = new Foo<T>(); //fails implicit cast Foo<IWorld> bar2 = (Foo<IWorld>)new Foo<T>(); //fails explicit cast } 

Since each T implements IWorld , each instance of Foo<T> must correspond to Foo<IWorld> . Why not? Is there any way around this? I really do not want to resort to generics to achieve this.

+7
source share
4 answers
 T : IWorld 

means that T was implemented by IWorld and does not mean that it ONLY implemented IWorld, and EXACTLY - IWorld. Other interfaces may also be implemented.

However, C # supports this conversion in later versions. See http://msdn.microsoft.com/en-us/library/dd799517.aspx (Covariance and contravariance in generics)

+1
source

You can move the object first

 Foo<IWorld> bar2 = (Foo<IWorld>)(object)new Foo<T>(); 
+1
source

An even simpler objection - imagine that instead of Foo it was, say, List .

By converting List<T> to List<IWorld> , I can now add another IWorld implementation IWorld (for example, type T2 ) to a list that is limited to only containing objects of type T This does not have to be reliable.

So, back to your Foo object - if it contains any methods that are expected to be called with objects of type T , now I can call them any object that implements IWorld - even if (imagine an additional Foo type) that the object is not would be a suitable type for Foo .


My point in the comments is re: type values. Again, this might be easier if we speak in terms of List<T> - a List<T> for value types containing value types without a box. If you want to use the List<IWorld> the same values, each value must be boxed before it is added to the list.

+1
source

What is the problem with the following

  Foo<IWorld> bar1 = new Foo<IWorld>(); 

What are you trying to achieve?

If you need to pass an instance of IWorld , you can safely pass T , but this is not the case in your code.

EDIT (based on comments)

To use Foo<Array of something> , you can use Cast or OfType depending on your requirement (whether you want to throw or ignore incompatible matches).

If it is .NET 4, it should work automatically due to the CoVariance function.

0
source

All Articles