为什么List.AddRange接受T []但不接受IEnumerable <t>

时间:2018-09-10 15:27:29

标签: c# list generics ienumerable

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

我写了这个方法:

nil

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

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

不起作用?

  

后面的示例将产生此错误:“参数1:无法从private void AddItems<T>(IEnumerable<T> items) where T : SomeClass { if (items != null) { someList.AddRange(items); } } 转换为System.Collections.Generic.IEnumerable<T>

System.Collections.Generic.IEnumerable<SomeClass>

error

1 个答案:

答案 0 :(得分:2)

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

IEnumerable<SomeSpecificClass>

您知道SomeSpecificClass始终从SomeClass继承。您想使用List<SomeClass>将该序列中的所有项目添加到AddRange()中。但是List<SomeClass>.AddRange是特定的;它恰好需要一个IEnumerable<SomeCass>,并且您不能直接从IEnumerable<SomeSpecificClass>投射到IEnumerable<SomeClass>。您可以使用简单的Cast<T>()来解决此问题:

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

现在的问题是数组为什么起作用,答案是数组以这种方式很特殊。它们不仅仅是泛型。您可以将SomeSpecificClass[]直接转换为SomeClass[],并且由于SomeClass[]实现了IEnumerable<SomeClass>,所以一切都很好。