【问题标题】:Why can't I add a List<T : Interface> to a List<List<Interface>>? [duplicate]为什么我不能将 List<T : Interface> 添加到 List<List<Interface>>? [复制]
【发布时间】:2014-10-20 16:17:15
【问题描述】:

我有一堆实现接口I 的对象列表。我想制作这些列表的列表并将它们作为一个单一的对象进行处理。我尝试创建一个List&lt;List&lt;I&gt;&gt; 并将我的其他列表添加到其中,在我看来这是有道理的,因为我添加的列表包含实现I 的对象,但编译器不允许我这样做。

例子:

public interface I
{
 //stuff
}

public class A : I
{
 //...
}
public class B : I
{
 //...
}

//elsewhere
public class C
{
    List<A> ListOfA; 
    List<B> ListOfB; 
    List<List<I>> ListOfLists;
    public C()
    {
        ListOfA = new List<A>();
        ListOfB = new List<B>();
        ListOfLists = new List<List<I>>();
        ListOfLists.Add(ListOfA); //nope
        ListOfLists.Add(ListOfB); //nope
    }
}

我有两个问题,第一个是为什么这是不允许的行为?第二个是我怎样才能完成我正在寻找的东西?

为了澄清,当我尝试将列表添加到 ListOfLists 时,我得到“无法从列表转换为列表”,其中 T : I。我使用的是 .NET 3.5,不,我无法升级到更高版本。

【问题讨论】:

标签: c# .net .net-3.5


【解决方案1】:

如果可以,你可以写:

List<I> listOfAs = ListOfLists[0];

var B = new B();
listOfAs.Add(B);

这显然是被禁止的,因为您不能将 B 实例添加到 A 的列表中。

Eric Lippert 的This answer 给出了一个很好的类似例子,用动物代替 As 和 Bs。

要回答您的第二个问题,我们需要按照您打算对 ListOfLists 执行的操作,在初始化后简单地枚举或修改集合。

如果这个想法只是拥有一个 I 实例的只读集合:

IEnumerable<I> collectionOfIs = ListOfA.Cast<I>().Concat(ListOfB.Cast<I>());

这是因为 List 实现了 IEnumerable

然后您可以使用 ToList 来实现集合并能够使用索引器:

List<I> listOfIs = collectionOfIs.ToList();

【讨论】:

  • 好点子,但是如果我想要一个包含所有其他列表元素的只读串联列表怎么办?
  • @Logan:那你要的类型是IEnumerable&lt;T&gt;,而不是List&lt;T&gt;
  • 啊哈!我错过了Concat 方法。让我快点试试。
  • @Logan 您需要在 usings 中引用 System.Linq
  • @Logan:如果您不想切换到 .NET 4.5,并且不想复制,那么您将不得不编写自己的代码,或者考虑使用类似这样的代码: IIndexable: A read-only list interface(免责声明:我写的)。它具有轻量级的只读包装类,可以动态投影元素(即在索引它们时投射它们,而不创建新列表)。 IE。在这种情况下,您将使用ListOfA.AsIndexable().Select(a =&gt; (I)a),它会返回可索引的只读集合。
【解决方案2】:

你需要使用IEnumerable&lt;I&gt;,因为List&lt;I&gt;是一个集合对象

    List<A> ListOfA;
    List<B> ListOfB;
    List<IEnumerable<I>> ListOfLists;
    public C()
    {
        ListOfA = new List<A>();
        ListOfB = new List<B>();
        ListOfLists = new List<IEnumerable<I>>();
        ListOfLists.Add(ListOfA);
        ListOfLists.Add(ListOfB);
    }

【讨论】:

  • 试过这个,不行。同样的问题,无法从 List 转换为 IEnumberable
  • @Logan 老兄我也试过这个:|,发布你的尝试
  • @Logan:这应该适用于 .NET 4.5 和更新版本,因为 IEnumerable&lt;T&gt; 的泛型类型参数是 covariant(即添加了 out 关键字:IEnumerable&lt;out T&gt;)。
  • 这也适用于我
  • 我正在使用 .NET 3.5,请查看我的标签 :) 我会更新问题以指定。
猜你喜欢
  • 2012-02-14
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多