【问题标题】:List<Ttype> to List<TInterface> in C#?C# 中的 List<Type> 到 List<Interface>?
【发布时间】:2012-12-18 04:39:53
【问题描述】:

我想在 C# 中做一些类似协变的事情,但我这里没有任何继承。

我有这个代码:

public interface IBirthday
{
   void Dance ();
}


public class Birthday:IBirthday
{
 public void Dance()
    {}
 }


void Main()
{
  List<Birthday> l= new List<Birthday>();
  List<IBirthday> d = l; //<--- How can I accomplish that ? 
}

我怎样才能完成这项工作? (除了手动迭代和构建(linq 或循环))

List<IBirthday> d = list of birthdays ? 

迭代/linq 是唯一的选择吗?

【问题讨论】:

  • 你试过Cast吗?
  • 你不能也不应该,正是因为缺乏协变,它不是类型安全的。不过,您应该可以使用IEnumerable&lt;IBirthday&gt; d = l;。
  • 为什么要List&lt;IBirthday&gt;?这是关键,用例似乎很小。
  • @millimoose - 考虑将其发布为答案。

标签: c# .net .net-4.0 interface


【解决方案1】:

不可能在不创建全新列表的情况下将List&lt;Birthday&gt; 分配给List&lt;IBirthday&gt;(它可以对您隐藏,但它必须发生在某个地方)。

如果您尝试做的事情是可能的,那么当有人这样做时会发生什么:

public class UnBirthday : IBirthday { ... }

d.Add(new UnBirthday());

嗯,它是List&lt;IBirthday&gt;,所以它认为它能够添加新项目。但底层列表实际上是List&lt;Birthday&gt;,您不能将UnBirthday 添加到该列表中。考虑到允许这个和只是在运行时崩溃之间的选择,C# 做出了决定(在我看来是正确的),首先不允许它。

使用泛型参数协方差的唯一方法,这是您正在尝试做的,是将它分配给只能读取信息而从不输入信息的东西。IEnumerable&lt;T&gt; 就是一个例子。每个Birthday 都是IBirthday,而IEnumerable 不可能被赋予IBirthday 而不是Birthday,所以说:

List<Birthday> l= new List<Birthday>();
IEnumerable<IBirthday> d = l;

工作得很好。

【讨论】:

  • 可以构造一个 ReadOnlyListWrapper&lt;T,U&gt; where U:T 来包装 IList&lt;U&gt; 并实现 IList&lt;T&gt;,并将其自身报告为只读。这样的东西将无法将T 存储在原始列表中,但会呈现列表的“实时”视图并且不需要复制它。
  • @supercat 这就是我在最后一段中介绍的内容,它只是协变接口的另一个示例。 (您可以在 .NET 4.5 中使用 IReadOnlyList,它适用于 List 或数组,其方式与 IEnumerable 相同。)
  • 我的意思是,即使没有任何内置类可以这样做,也可以轻松编写一个包装类,允许将IList&lt;U&gt; 用作IList&lt;T&gt; (允许按索引读取单个项目,“实时”),而不仅仅是IEnumerable&lt;T&gt;。
  • @supercat 是的,我提供了一个示例界面,它不是唯一一个。 IReadOnlyList 是另一个,如果你愿意,你可以自己制作。只要你只是阅读信息,你就可以做到。
【解决方案2】:

你可以使用:

d = l.Cast<IBirthday>.ToList();

【讨论】:

  • 这不是为现有列表分配新视图,它只是创建一个全新的列表。这在语义上可能是也可能不是你想要的。
  • 我没有写过迭代(niether linq)
  • @Servy 没错,我没有考虑到这一点。我不知道你会如何解决这个问题
  • @TheEvilPenguin 你不会的。这就是答案。不建立一个新列表是不可能的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 2013-09-21
  • 2012-02-14
  • 1970-01-01
相关资源
最近更新 更多