¿Por qué una operación Linq Cast falla cuando tengo un molde implícito definido?

Creé dos clases, una de ellas tiene un reparto implícito entre ellas:

public class Class1 { public int Test1; } public class Class2 { public int Test2; public static implicit operator Class1(Class2 item) { return new Class1{Test1 = item.Test2}; } } 

Cuando creo una nueva lista de un tipo y trato de enviar al otro, falla con una InvalidCastException:

 List items = new List{new Class2{Test2 = 9}}; foreach (Class1 item in items.Cast()) { Console.WriteLine(item.Test1); } 

Esto, sin embargo, funciona bien:

 foreach (Class1 item in items) { Console.WriteLine(item.Test1); } 

¿Por qué no se llama al lanzamiento implícito cuando se usa Cast ?

Porque, al mirar el código a través de Reflector, Cast no intenta tomar en cuenta a los operadores de conversión implícita (el código LINQ Cast está muy optimizado para casos especiales de todo tipo, pero nada en esa dirección) (ya que muchos lenguajes .NET no lo harán) )

Sin entrar en la reflexión y otras cosas, los generics no ofrecen ninguna manera de incorporar esas cosas adicionales en cualquier caso.

EDITAR: en general, las instalaciones genéricas como LINQ no suelen ocuparse de instalaciones más complejas como implícita / explícita, operadores de igualdad, etc.

También puede usar esto para hacer casting con conversiones si es necesario:

 public static IEnumerable CastAll(this IEnumerable items) { var p = Expression.Parameter(typeof(TItem), "i"); var c = Expression.Convert(p, typeof(TDest)); var ex = Expression.Lambda>(c, p).Compile(); foreach (var item in items) { yield return ex(item); } } 

Desde http://adventuresdotnet.blogspot.com/2010/06/better-more-type-safe-alternative-to.html

Gracias por eso estuve a punto de usar ese caso exacto en alguna parte. Me has ahorrado un montón de tiempo. Como una posible solución a su problema, podría usar ConvertAll <> en su lugar, así:

 foreach (Class1 item in items.ConvertAll((i) => (Class1)i)) { Console.WriteLine(item.Test1); } 

EDITAR: o si quieres ser más explícito de que el elenco está implícito, esto también funciona:

 foreach (Class1 item in items.ConvertAll(i => i)) { Console.WriteLine(item.Test1); } 

Una solución podría ser usar un poco de linq aquí si realmente necesita este tipo de conversión:

 Lista de elementos = nueva lista {new Class2 {Test2 = 9}};
 foreach (elemento de Class1 en (de x en elementos select (Class1) x))
 {
     Console.WriteLine (item.Test1);
 }