I am sure I am missing something simple, however I am trying to convert a strongly typed list of objects that all implement an interface in to a list of that interface type.
Below is a sample to demonstrate the error:
public void ExampleCode(){
List<Cube> cubes = new List<Cube>();
List<Shape> allShapes;
allShapes = cubes;//Syntax Error
allShapes = (List<Shape>)cubes;//Syntax Error
}
public class Cube : Shape
{
public int ID { get; set; }
public int Sides { get; set; }
}
public interface Shape
{
int ID { get; set; }
int Sides { get; set; }
}
Instead of casting like that, try:
allShapes = cubes.Cast<Shape>().ToList();
You need .NET 3.5 for this. I believe the Cast extension method can be found in System.Linq.
You can't. Because List<T>
and ILIst<T>
to only support invariant type parameters. This is down to T
being both use for input and output parameters (eg return values). Otherwise you can break the type safety.
Other interfaces (eg IEntumerable<T>
) do allow some variance.
See Eric Lippert's blog " Fabulous Adventures In Coding " for discussion of contra- and co-variance. Specifically the " Covariance and Contravariance " tag.
Edit, just added to the "C# Frequently Asked Questions" blog: Covariance and Contravariance FAQ
What you are referring to is called generic covariance and is not supported by c# 3. It is, however, supported by c# 4 (.NET 4 / VS 2010) and you can read more about it here:
Having said that, IList<T>
is not covariant (because it both accepts and exposes T
). IEnumerable<T>
, on the other hand, is covariant (because it doesn't accept T
).
You cannot do this since by casting this way you can potentially lose all type safety. For instnce, casting List<Shape>
to List<object>
will result in that objects of any type can be added to the list, which will be downright inconsistent.
You can also do:
allShapes = cubes.ConvertAll(x => (Shape)x);
Or if you are doing this in .NET 2.0:
allShapes = cubes.ConvertAll<Shape>(delegate(Cube c){
return (Shape)c;
});
You can't cast between lists of types, even if the types themselves are convertible. You will need to create a new list and populate it, either by iterating the original list or by using ConvertAll. See http://www.dev102.com/2008/05/15/how-to-convert-listt1-to-listt2/ for sample code.
This works if you define allShapes as IEnumerable
In C# 4.0 you may simply assign allshapes=cubes
For C# 3.5 you could use allShapes = cubes.Select(c=>((Shape)c));
But in any case you need to use IEnumerable instead of List
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.