Por que um elenco Linq operação falhar quando eu tenho uma conversão implícita definida?
Pergunta
Eu criei duas classes, com um deles tendo uma conversão implícita entre eles:
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};
}
}
Quando eu criar uma nova lista de um tipo e tentar Elenco
List<Class2> items = new List<Class2>{new Class2{Test2 = 9}};
foreach (Class1 item in items.Cast<Class1>())
{
Console.WriteLine(item.Test1);
}
Isso, no entanto, bem funciona:
foreach (Class1 item in items)
{
Console.WriteLine(item.Test1);
}
Porque é que a conversão implícita não é chamado quando se utiliza Elenco
Solução
Porque, olhando para o código via refletor, tentativa doesnt de molde a tomar quaisquer operadores de conversão implícita (o código LINQ Elenco é altamente otimizado para casos especiais de todos os tipos, mas nada nessa direção) em conta (como muitas linguagens .NET não).
Sem entrar em reflexão e outras coisas, genéricos doesnt oferecem qualquer fora da caixa caminho a tomar tal material extra em conta em qualquer caso.
EDIT:. Em instalações em geral, mais complexos como implícito / explict, operadores de igualdade etc. geralmente não são manipulados por instalações genéricos como LINQ
Outras dicas
Você também pode usar isso para fazer fundição com conversões, se necessário:
public static IEnumerable<TDest> CastAll<TItem, TDest>(this IEnumerable<TItem> items)
{
var p = Expression.Parameter(typeof(TItem), "i");
var c = Expression.Convert(p, typeof(TDest));
var ex = Expression.Lambda<Func<TItem, TDest>>(c, p).Compile();
foreach (var item in items)
{
yield return ex(item);
}
}
A partir http: //adventuresdotnet.blogspot .com / 2010/06 / melhor-mais-type-safe-alternativo-to.html
Obrigado por que eu estava prestes a usar esse exato em algum caso. Você me salvou um monte de tempo. Como uma possível solução para o seu problema, você poderia usar ConvertAll <> em vez, assim:
foreach (Class1 item in items.ConvertAll<Class1>((i) => (Class1)i))
{
Console.WriteLine(item.Test1);
}
EDIT: ou se você quiser ser mais explícito que o elenco está implícito, então isso funciona também:
foreach (Class1 item in items.ConvertAll<Class1>(i => i))
{
Console.WriteLine(item.Test1);
}
Uma solução poderia ser a de usar um pouco de linq'ing aqui se você realmente precisa deste tipo de conversão:
List items = new List{new Class2{Test2 = 9}}; foreach (Class1 item in (from x in items select (Class1)x)) { Console.WriteLine(item.Test1); }