Linq Cast< T>暗黙的なキャストが定義されていると操作が失敗しますか?
質問
2つのクラスを作成しましたが、そのうちの1つは暗黙的なキャストを持ちます:
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};
}
}
1つのタイプの新しいリストを作成し、Cast< T>をキャストしようとするともう一方は、InvalidCastExceptionで失敗します:
List<Class2> items = new List<Class2>{new Class2{Test2 = 9}};
foreach (Class1 item in items.Cast<Class1>())
{
Console.WriteLine(item.Test1);
}
ただし、これは正常に機能します。
foreach (Class1 item in items)
{
Console.WriteLine(item.Test1);
}
Cast&lt; T&gt;を使用するときに暗黙のキャストが呼び出されないのはなぜですか?
解決
Reflectorを介してコードを見ると、Castは暗黙のキャスト演算子(LINQ Castコードはあらゆる種類の特殊なケースに対して高度に最適化されていますが、その方向には何も考慮していません)を考慮しません(多くの.NET言語として)ありません)。
リフレクションなどを使用することなく、ジェネリックは、そのような余分なものを考慮に入れるための独創的な方法を提供しません。
編集:一般に、暗黙的/明示的、等号演算子などのより複雑な機能は、LINQなどの汎用機能では通常処理されません。
他のヒント
必要に応じて、これを使用してコンバージョンを伴うキャストを行うこともできます。
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);
}
}
http://adventuresdotnet.blogspotから.com / 2010/06 / better-more-type-safe-alternative-to.html
おかげで、どこかでその正確なケースを使用しようとしていました。あなたは私に時間の山を救いました。問題の可能な解決策として、ConvertAll&lt;&gt;代わりに、次のようになります。
foreach (Class1 item in items.ConvertAll<Class1>((i) => (Class1)i))
{
Console.WriteLine(item.Test1);
}
編集:または、キャストが暗黙的であることをより明示的にしたい場合、これも機能します:
foreach (Class1 item in items.ConvertAll<Class1>(i => i))
{
Console.WriteLine(item.Test1);
}
この種の変換が本当に必要な場合、ここでの解決策は少しのlinq'ingを使用することです:
List items = new List{new Class2{Test2 = 9}}; foreach (Class1 item in (from x in items select (Class1)x)) { Console.WriteLine(item.Test1); }