web-dev-qa-db-ja.com

List <T>をList <Interface>にキャスト

public interface IDic
{
    int Id { get; set; }
    string Name { get; set; }
}
public class Client : IDic
{

}

List<Client>からList<IDic>

96

cast it(参照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];

これで、List<Apple>からIEnumerable<IFruit>は共分散による.NET 4/C#4ですが、必要な場合はList<IFruit>newリストを作成する必要があります。例えば:

// 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();

しかし、これはnotは元のリストのキャストと同じです。これは、2つのseparateリストがあるためです。これは安全ですが、一方のリストに加えられた変更(しないがもう一方のリストに反映されることを理解する必要があります。 (もちろん、リストが参照するobjectsの変更は表示されます。)

220
Jon Skeet

キャストイテレータと.ToList():

List<IDic> casted = input.Cast<IDic>().ToList()はトリックを行います。

当初、共分散が機能すると述べましたが、ジョンが正しく指摘したように。いいえ、できません!

そしてもともと私は愚かにもToList()呼び出しを中断しました

5
Andras Zoltan

私もこの問題を抱えていたので、Jon Skeetの答えを読んだ後、コードをList<T>からIEnumerable<T>に変更しました。これは、OPの元々の質問であるList<Client>List<IDic>にキャストする方法には答えませんが、そうする必要はありません。この問題。もちろん、これはList<IDic>の使用を必要とするコードが管理下にあることを前提としています。

例えば。:

public void ProcessIDic(IEnumerable<IDic> sequence)
{
   // Implementation
}

の代わりに:

public void ProcessIDic(List<IDic> list)
{
   // Implementation
}
4
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
2
Marc Messing

LINQを使用できる場合、これを実行できます...

List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
2
musefan

.Net 3.5では、次のことができます。

List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());

この場合のListのコンストラクターは、IEnumerableを受け取ります。
リストただし、IEnumerableにのみ変換可能です。 myObjはISomeInterfaceに変換可能ですが、IEnumerable型はIEnumerableに変換できません。

0
Kent Aguilar

新しいList<IDic>を作成し、すべての要素を転送することによってのみ可能です。

0
Piotr Auguscik