IEnumerable.ToArray<T>()与IEnumerable.Cast<T>().ToArray()的区别

5
当我试图从一个IEnumerable对象集合中获取一个对象数组(与我想要的数组类型不同),我知道我可以先将源集合转换为正确的类型,然后从中获取一个数组,但是方法ToArray()给我一种它可以在一步中处理这两个操作的印象。然而,根据我的经验,我从来没有找到过ToArray()方法适用于除原始源T之外的任何T的情况(在我看来,这使得ToArray()变得可笑,因为它做的事情与非泛型ToArray()已经做了相同的事情)。
所以我的问题是,我是否误解了ToArray()方法的意义,我试图让它做一些它从未打算做的事情,还是我在关于该方法方面缺少了什么,并且我正在尝试做的事情通常符合其意图?
以下是一个具体的示例,以说明我的问题:
public interface IFoo { }
public class Foo : IFoo { }

static void Main(string[] args)
{
    // Suppose a list of Foos was created
    List<Foo> src = new List<Foo>();

    // I would be safe obtaining an array of IFoos from that list, but

    // This is not supported (although intellisense shows the method is there, the compiler balks):
    // IFoo[] results = src.ToArray<IFoo>();

    // Whereas this works just fine:
    IFoo[] results = src.Cast<IFoo>().ToArray();
}
1个回答

9
< p > ToArray<T>() 是泛型的原因是它可以操作任何 IEnumerable<T>,而不是你可以提供不同的 T

public static T[] ToArray<T>(this IEnumerable<T> self) { ... }

您不应该自己提供T。如果您这样做,就像您的示例一样,该方法将期望接收例如IEnumerable<IFoo>,而您没有提供。

顺便说一下,没有“非泛型ToArray()”。编译器根据您调用ToArray()的可枚举类型推断出T泛型参数。


这很有道理,看起来我混淆了ToArray()和ToArray<T>()。我本以为它们是两个不同的方法,但实际上ToArray()只是将其重定向到基于源IEnumerable的T的隐式解释ToArray<T>()。也许这是个人偏见,但我仍然觉得这似乎有点尴尬。也许这就是泛型的本质。我认为应该有一种方法来“隐藏”通用类型T,但我无法想出一个好的方法来做到这一点,因为(如您所提到的)IEnumerable需要一个T。无论如何,感谢您的答案。 - Steven
没问题。是的,你说得对——它们是同一个方法。如果你调用一个泛型方法并且没有提供任何类型参数,编译器会尝试为你推断它们。听起来有些别扭,但可以节省很多打字时间。想象一下,如果你有一个List<Dictionary<string,List<int>>>——.ToArray()比.ToArray<Dictionary<string,List<int>>>()更好。(顺便说一句,如果存在非泛型方法,并且你的参数与其签名兼容,则编译器将优先选择非泛型方法,否则它将寻找可用的泛型重载。) - cdhowie
1
在C#4中是否可以使用不同的 T,因为 IEnumerable<out T> 中的 T 是协变的? - CodesInChaos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接