Por que um elenco Linq operação falhar quando eu tenho uma conversão implícita definida?

StackOverflow https://stackoverflow.com/questions/808725

  •  03-07-2019
  •  | 
  •  

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 para o outro, ele falha com um InvalidCastException:

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 ?

Foi útil?

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);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top