public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
私はどのようにキャストすることができますList<Client>
するにはList<IDic>
?
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
私はどのようにキャストすることができますList<Client>
するにはList<IDic>
?
回答:
キャストすることはできません(参照IDを保持)-安全ではありません。例えば:
public interface IFruit {}
public class Apple : IFruit {}
public class Banana : IFruit {}
...
List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());
// Eek - it's a banana!
Apple apple = apples[0];
これで、共分散のために.NET 4 / C#4でa List<Apple>
をに変換できますがIEnumerable<IFruit>
、List<IFruit>
必要な場合は新しいリストを作成する必要があります。例えば:
// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();
// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();
しかし、これは元のリストをキャストすることと同じではありません。別個のリストです。これは安全ですが、一方のリストに加えられた変更はもう一方のリストには反映されないことを理解する必要があります。(もちろん、リストが参照するオブジェクトへの変更は表示されます。)
List<IFruit>
実際にはへの参照であるコンパイル時の型の参照ができると仮定しますList<Apple>
。これにBanana
参照を追加するとどうなると思いますList<IFruit>
か?
using
ディレクティブがあるのかSystem.Linq
、それを呼び出そうとしているのか、私にはわかりません。さらに調査することをお勧めします。それでも解決しない場合は、最小限の再現可能な例で質問します。
キャストイテレータと.ToList():
List<IDic> casted = input.Cast<IDic>().ToList()
トリックを行います。
元々、共分散が機能すると述べましたが、ジョンが正しく指摘しているように; いいえ、そうではありません!
そして、もともと私は愚かにToList()
電話をやめました
Cast
安全ではないので、IEnumerable<T>
ではなく、を返しますList<T>
-そして、いいえ、共分散はこの変換を許可しません-私の答えを見てください。
ToList()
あなたのコメントを読む前に欠落していることに気づきました; もちろん、もちろん示しましたが、共分散は機能しません。どー!
Cast
、type引数をに指定する限り、.NET 4での呼び出しが不要であることを意味するため、引き続き役立ちますToList
。
私にもこの問題があり、Jon Skeetの回答を読んだ後、コードをList<T>
からuse に変更しましたIEnumerable<T>
。これはのOPの元の質問に答えるしませんが、私はキャストすることができますどのようにList<Client>
するList<IDic>
ため、それはそうする必要性を回避しないと、この問題が発生した他の人に役立つかもしれません。もちろん、これはの使用を必要とするコードがList<IDic>
あなたの管理下にあると想定しています。
例えば:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
の代わりに:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
新規に作成してList<IDic>
すべての要素を転送することによってのみ可能です。
.Net 3.5では、次のことができます。
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
この場合のListのコンストラクターはIEnumerableを取ります。ただし、
リストはIEnumerableにのみ変換可能です。myObjをISomeInterfaceに変換できる場合でも、IEnumerable型はIEnumerableに変換できません。