【问题标题】:Why does List.AddRange accept T[] but doesn't accept IEnumerable<T>为什么 List.AddRange 接受 T[] 但不接受 IEnumerable<T>
【发布时间】:2018-09-10 15:27:29
【问题描述】:

所以我试图稍微重构一下我的代码,我需要一个方法来检查数组是否为空,然后是否不将该数组中的项目添加到列表中。我需要将许多从同一类继承的不同项目添加到该类的列表中。

我写了这个方法:

private void AddItems<T>(T[] items) where T : SomeClass
    {
        if (items != null)
        {
            someList.AddRange(items);
        }
    }

这很好用,但是我的问题是为什么会这样:

private void AddItems<T>(IEnumerable<T> items) where T : SomeClass
    {
        if (items != null)
        {
            someList.AddRange(items);
        }
    }

不工作?

后一个示例产生此错误:“参数 1:无法从 System.Collections.Generic.IEnumerable&lt;T&gt; 转换为 System.Collections.Generic.IEnumerable&lt;SomeClass&gt;

List<SomeClass> someList = new List<SomeClass>();

error

【问题讨论】:

  • 请分享someList的定义。还有不工作是什么意思?编译错误?如果是,请提供哪个
  • 这看起来很奇怪,因为the method declarationList&lt;T&gt;.AddRange(IEnumerable&lt;T&gt;)。它以什么方式“不起作用”?
  • 请定义“不工作”。你有错误吗?什么错误?
  • 取决于您使用的 .Net 版本。较旧的不支持IEnumerable&lt;T&gt;。虽然 6 可以。
  • 为什么不用IEnumerable&lt;SomeClass&gt; items作为参数?

标签: c# list generics ienumerable


【解决方案1】:

这与数组和泛型的工作方式有关。你有一个像这样键入的变量:

IEnumerable<SomeSpecificClass>

您知道SomeSpecificClass 总是继承自SomeClass。您想使用AddRange() 将该序列中的所有项目添加到List&lt;SomeClass&gt;。但是List&lt;SomeClass&gt;.AddRange 是特定的;它只需要一个IEnumerable&lt;SomeCass&gt;,并且您不能直接从IEnumerable&lt;SomeSpecificClass&gt; 转换为IEnumerable&lt;SomeClass&gt;。你可以用一个简单的Cast&lt;T&gt;() 来解决这个问题:

someList.AddRange(items.Cast<SomeClass>());

现在的问题是数组为什么起作用,答案是数组在这种方式上是特殊的。它们不仅仅是泛型。你可以直接将SomeSpecificClass[] 转换为SomeClass[],由于SomeClass[] 实现了IEnumerable&lt;SomeClass&gt;,所以一切都已经好了。

【讨论】:

  • 是的,这正是我要问的,我知道如何解决问题。为什么第一个有效而后者无效的问题,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
  • 2014-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-27
相关资源
最近更新 更多