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

Why does List.AddRange accept T[] but doesn't accept IEnumerable<T>

所以我试图稍微重构我的代码,我需要一种方法来检查数组是否为 null,然后如果不为空,则将该数组中的项目添加到列表中。我需要将许多继承自相同 class 的不同项目添加到 class.

的列表中

我写了这个方法:

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);
        }
    }

不工作?

The latter example produces this error: "Argument 1: cannot convert from System.Collections.Generic.IEnumerable<T> to System.Collections.Generic.IEnumerable<SomeClass>"

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

error

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

IEnumerable<SomeSpecificClass>

你知道 SomeSpecificClass 总是继承自 SomeClass。您想要使用 AddRange() 将该序列中的所有项目添加到 List<SomeClass>。但是 List<SomeClass>.AddRange 是特定的;它正好需要一个 IEnumerable<SomeCass>,你不能直接从 IEnumerable<SomeSpecificClass> 转换为 IEnumerable<SomeClass>。你可以用一个简单的 Cast<T>():

来解决这个问题
someList.AddRange(items.Cast<SomeClass>());

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