Perché un Linq Cast < T > operazione fallita quando ho definito un cast implicito?

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

  •  03-07-2019
  •  | 
  •  

Domanda

Ho creato due classi, una delle quali ha un cast implicito tra di loro:

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 creo un nuovo elenco di un tipo e provo a trasmettere < T > all'altro, fallisce con InvalidCastException:

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

Questo, tuttavia, funziona bene:

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

Perché il cast implicito non viene chiamato quando si utilizza Cast < T > ;?

È stato utile?

Soluzione

Perché, guardando il codice tramite Reflector, Cast non tenta di prendere in considerazione operatori cast impliciti (il codice LINQ Cast è fortemente ottimizzato per casi speciali di ogni tipo, ma nulla in quella direzione) (come molti linguaggi .NET non lo faranno).

Senza riflettere e altre cose, i generici non offrono alcun modo per prendere in considerazione tali cose extra in ogni caso.

EDIT: in generale, strutture più complesse come implicite / esplicite, operatori di uguaglianza ecc. non sono generalmente gestite da strutture generiche come LINQ.

Altri suggerimenti

Puoi anche utilizzarlo per eseguire il cast con le conversioni, se necessario:

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);
 }
}

Da http: //adventuresdotnet.blogspot .com / 2010/06 / migliore-più-type-safe-alternative-to.html

Grazie per quello che stavo per usare quel caso esatto da qualche parte. Mi hai risparmiato un sacco di tempo. Come possibile soluzione al tuo problema, puoi utilizzare ConvertAll < > invece, in questo modo:

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

EDIT: o se vuoi essere più esplicito che il cast è implicito, allora funziona anche questo:

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

Una soluzione potrebbe essere quella di utilizzare un po 'di linq'ing qui se hai davvero bisogno di questo tipo di conversione:

List items = new List{new Class2{Test2 = 9}};
foreach (Class1 item in (from x in items select (Class1)x))
{
    Console.WriteLine(item.Test1);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top