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>
?
Answers:
您不能强制转换(保留参考身份)-那是不安全的。例如:
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>
你必须建立一个新的列表。例如:
// 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>
什么?
Cast迭代器和.ToList():
List<IDic> casted = input.Cast<IDic>().ToList()
会成功的
最初,我说协方差是可行的-但正如乔恩正确指出的那样;不,不会!
最初我也愚蠢地拒绝了ToList()
电话
Cast
返回一个- IEnumerable<T>
,而不是List<T>
-,并且不,协方差将不允许这种转换,因为这将是不安全的-请参阅我的答案。
ToList()
在阅读您的评论之前,我已经意识到缺少;但是是的,正如您所展示的,协方差当然是行不通的!h!
Cast
只要在.NET 4中指定类型参数,就不需要在.NET 4中进行调用ToList
。
我也遇到了这个问题,在阅读了Jon Skeet的回答后,我将代码从using修改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>
元素并转移所有元素,才有可能。