投射列表<T>到列表<接口>
public interface IDic { int Id { get; set; } string Name { get; set; } } public class Client : IDic { }
我怎样才能将List<Client>
为List<IDic>
?
你不能投它(保存参考身份) – 这是不安全的。 例如:
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>
转换为.NET 4 / C#4中的IEnumerable<IFruit>
,但是如果您需要List<IFruit>
,则必须创build一个新列表。 例如:
// 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();
但这不像铸造原始列表 – 因为现在有两个单独的列表。 这是安全的,但是您需要了解对一个列表所做的更改不会在其他列表中看到。 (当然,可以看到列表引用对象的修改。)
Cast迭代器和.ToList():
List<IDic> casted = input.Cast<IDic>().ToList()
会做的。
本来我说协变会奏效 – 但是正如Jon所指出的那样。 不,它不会!
最初我也愚蠢地离开了ToList()
调用
如果你可以使用LINQ,那么你可以这样做…
List<Client> clientList = new List<Client>(); List<IDic> list = clientList.Select(c => (IDic)c).ToList();
List<Client> listOfA = new List<Client>(); List<IDic> list = listOfA.Cast<IDic>().ToList();
我也有这个问题,并阅读Jon Skeet的答案我修改我的代码从使用List<T>
使用IEnumerable<T>
。 尽pipe这并不回答OP 如何将List<Client>
为List<IDic>
的原始问题,但它确实避免了这样做的需要,因此可能对遇到此问题的其他人有所帮助。 这当然假设需要使用List<IDic>
的代码在您的控制之下。
例如:
public void ProcessIDic(IEnumerable<IDic> sequence) { // Implementation }
代替:
public void ProcessIDic(List<IDic> list) { // Implementation }
它只能通过创build新的List<IDic>
和传输所有元素。
在.net 3.5中,您可以执行以下操作:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
在这种情况下List的构造函数需要一个IEnumerable。
列表虽然只能转换为IEnumerable。 即使myObj可以转换为ISomeInterfacetypesIEnumerable不可转换为IEnumerable。