Cast List<T> to List<Interface>

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


}

How can I cast List<Client> to List<IDic>?

70161 次浏览

它只有通过创建新的 List<IDic>和转移所有元素才有可能。

一个 Cast 迭代器和. ToList () :

List<IDic> casted = input.Cast<IDic>().ToList()就行了。

最初我说协方差会起作用——但正如乔恩正确地指出的那样; 不,它不会起作用!

而且最初我还愚蠢地中断了 ToList()的电话

如果你可以使用 LINQ 然后你可以这样做..。

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

你不能 演员它(保留参考标识)-这将是不安全的。例如:

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由于协方差,但是如果你想要一个 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<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();

我也有这个问题,在读了 Jon Skeet 的答案之后,我修改了我的代码,从使用 List<T>改为使用 IEnumerable<T>。虽然这并不能回答 OP 最初提出的 如何将 ABC2转换为 List<IDic>问题,但是它确实避免了这样做的需要,因此可能对遇到这个问题的其他人有所帮助。当然,这是假设需要使用 List<IDic>的代码在您的控制之下。

例如:

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

而不是:

public void ProcessIDic(List<IDic> list)
{
// Implementation
}

在.Net 3.5中,你可以做以下事情:

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

在这种情况下,List 的构造函数接受 IEnumable。
List 不过只能转换为 IEnumable。即使 我的奥比可以转换为 ISomInterface,IEnumable 类型也不能转换为 IEnumable。

OfType

你可以试试这样:

        using (var dbContext = YourDatabaseContext())
{
var list = dbContext.Clients.Where(x => x.Happy)
.OfType<IDic>()
.ToList();
}

参见 https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.oftype

如果希望在不创建单独引用的情况下处理原始列表,可以像下面这样定义泛型方法:

public void DoIterate<T>(List<T> myCollection) where T : IDic
{
foreach (T item in myCollection)
{
//update a property of interface
item.Name = "new Name";
}
}

调用上面的方法来处理列表,而不必将特定对象强制转换为接口:

List<Client> clients = new List<Client>();
DoIterate(clients);

如果不需要修改原始列表的内容,可以隐式地将 List 转换为 IReadOnlyList,这样就可以将其内容作为 IDics 进行迭代,而无需创建新列表。

List<Client> myClients = new List<Client>();
myClients.Add(new Client());


IReadOnlyList<IDic> castedClients = myClients;
foreach(IDic val in castedClients)
{
//do something;
}

转换也可以像下面这样简单地返回列表:

public IReadOnlyList<IDic> getClientsAsIDic()
{
return myClients;
}