Pourquoi Linq Cast < T > l'opération échoue-t-elle lorsque j'ai un cast implicite défini?

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

  •  03-07-2019
  •  | 
  •  

Question

J'ai créé deux classes, l'une d'entre elles ayant une distribution implicite entre elles:

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

Lorsque je crée une nouvelle liste d'un type et que j'essaie de diffuser < T > de l'autre, il échoue avec une exception InvalidCastException:

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

Cela fonctionne cependant très bien:

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

Pourquoi la conversion implicite n'est-elle pas appelée lors de l'utilisation de la conversion < T >?

Était-ce utile?

La solution

Parce que, regardant le code via Reflector, Cast ne tente pas de prendre en compte les opérateurs de casting implicites (le code LINQ Cast est fortement optimisé pour les cas particuliers de toutes sortes, mais rien dans cette direction) (ainsi que de nombreux langages .NET pas).

Sans entrer dans la réflexion ni dans d’autres choses, les génériques n’offrent aucune solution immédiate permettant de prendre en compte ces éléments supplémentaires dans tous les cas.

EDIT: En général, les installations plus complexes telles que implicite / explicite, les opérateurs d'égalité, etc. ne sont généralement pas gérées par des installations génériques telles que LINQ.

Autres conseils

Vous pouvez également l'utiliser pour effectuer des conversions avec conversions si nécessaire:

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

De http: //adventuresdotnet.blogspot .com / 2010/06 / meilleur-plus-type-alternative-à -.html

Merci pour cela, j'étais sur le point d'utiliser ce cas exact quelque part. Tu m'as économisé du temps. Vous pouvez utiliser ConvertAll < > comme solution possible à votre problème. au lieu de cela, comme suit:

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

EDIT: ou si vous voulez être plus explicite sur le fait que la conversion est implicite, alors cela fonctionne aussi:

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

Une solution pourrait consister à utiliser un peu de linq'ing ici si vous avez vraiment besoin de ce type de conversion:

List items = new List{new Class2{Test2 = 9}};
foreach (Class1 item in (from x in items select (Class1)x))
{
    Console.WriteLine(item.Test1);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top