将List <T>转换为List <Interface>

And*_*kov 100 .net c# casting interface

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

}
Run Code Online (Sandbox Code Playgroud)

我怎样才能投List<Client>List<IDic>

Jon*_*eet 228

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

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];
Run Code Online (Sandbox Code Playgroud)

现在你可以转换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();
Run Code Online (Sandbox Code Playgroud)

但是,这是一样的铸造原名单-因为现在有两个单独的列表.这是安全的,但您需要了解对一个列表所做的更改将不会在另一个列表中看到.(当然,将会看到列表引用的对象的修改.)

  • 就像他们"还在建筑物里"一样! (6认同)
  • @RobertNoack:“对象引用”是什么意思?每个* element *的对象引用都是相同的,但这与强制转换列表引用本身不同。假设您可以强制转换引用,以便您具有编译时类型List &lt;IFruit&gt;的引用,该引用实际上是对List &lt;Apple&gt;的引用。如果您在该List &lt;IFruit&gt;上添加了Banana引用,将会发生什么? (3认同)
  • @TrươngQuốcKhhh:我不知道您的代码的*任何*是什么样子,或者您是否对System.Linq使用了using指令,或者您想调用它的方式,我不确定您希望我能够提供帮助。我建议您进行更多研究,如果仍然遇到问题,可以用[mcve]提问。 (2认同)
  • @JamesJoyce:“但为什么不反过来呢?” 正是因为这就是您最终添加香蕉的方式 - 如果您可以执行该任务。`List&lt;IFruit&gt;fruit = apples; 中的哪个语句;Fruit.Add(new Banana());` 你希望它不起作用吗? (2认同)
  • @Shiv:如果您愿意,为“IReadOnlyList&lt;T&gt;”添加自己的“ForEach”扩展方法很简单。我建议在这样做之前阅读 https://ericlippert.com/2009/05/18/foreach-vs-foreach/ 。 (2认同)

And*_*tan 5

Cast迭代器和.ToList():

List<IDic> casted = input.Cast<IDic>().ToList() 会成功的

最初,我说协方差是可行的-但正如乔恩正确指出的那样;不,不会!

最初我也愚蠢地拒绝了ToList()电话


mus*_*fan 5

如果你会使用 LINQ 那么你可以这样做......

List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
Run Code Online (Sandbox Code Playgroud)


小智 5

List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
Run Code Online (Sandbox Code Playgroud)


Ɖia*_*zeƦ 5

我也有这个问题,在阅读了 Jon Skeet 的回答后,我将代码从 using 修改List<T>为 use IEnumerable<T>。尽管这不能回答 OP 的原始问题How can I cast List<Client>toList<IDic>,但它确实避免了这样做的需要,因此可能对遇到此问题的其他人有所帮助。这当然假设需要使用的代码List<IDic>在您的控制之下。

例如:

public void ProcessIDic(IEnumerable<IDic> sequence)
{
   // Implementation
}
Run Code Online (Sandbox Code Playgroud)

代替:

public void ProcessIDic(List<IDic> list)
{
   // Implementation
}
Run Code Online (Sandbox Code Playgroud)