将数组转换为IEnumerable<T>

87

假设您有一个基本的Employee类,如下所示:

class Employee
{
   public string Name;
   public int Years;
   public string Department;
}

然后(在另一个类中),我有以下代码片段(我认为除了最后一个,都理解了):

我相信以下代码片段之所以有效,是因为数组初始化器创建了与分配给workforce变量相同类型的Employee对象数组。

Employee[] workforceOne = new Employee[] {
   new Employee() { Name = "David", Years = 0, Department = "software" },
   new Employee() { Name = "Dexter", Years = 3, Department = "software" },
   new Employee() { Name = "Paul", Years = 4, Department = "software" } };

我随后有以下代码片段。我认为这可以工作,因为Employee对象的数组隐式地是Array()类的实现,而该类实现了IEnumerable。因此,我认为这就是为什么该数组可以分配给IEnumerable的原因?

IEnumerable workforceTwo = new Employee[] {
   new Employee() { Name = "David", Years = 0, Department = "software" },
   new Employee() { Name = "Dexter", Years = 3, Department = "software" },
   new Employee() { Name = "Paul", Years = 4, Department = "software" } };

然后我有这段代码片段:

IEnumerable<Employee> workforceThree = new Employee[] {
   new Employee() { Name = "David", Years = 0, Department = "software" },
   new Employee() { Name = "Dexter", Years = 3, Department = "software" },
   new Employee() { Name = "Paul", Years = 4, Department = "software" } };

我不确定为什么这段代码可以工作?IEnumerable<Employee>继承自IEnumerable(并重写(或者重载?)了GetEnumerator()方法),但是我是否因此需要将上述代码强制转换才能正常工作:

//The cast does work but is not required
IEnumerable<Employee> workforceFour = (IEnumerable<Employee>)new Employee[] {
   new Employee() { Name = "David", Years = 0, Department = "software" },
   new Employee() { Name = "Dexter", Years = 3, Department = "software" },
   new Employee() { Name = "Paul", Years = 4, Department = "software" } };

看起来数组正在被隐式地从类型 IEnumerable 转换为 IEnumerable<Employee>,但我一直认为当你需要将一个类型转换为更具体的类型时,需要显式转换。

也许我的理解中缺少了一些简单的东西,但有人能帮助我理解一下吗?

谢谢。


3
在“workforceThree”片段的正下方。 - Heinzi
3个回答

121

根据文档

在.NET Framework版本2.0中,Array类实现了System.Collections.Generic.IList<T>、System.Collections.Generic.ICollection<T>和System.Collections.Generic.IEnumerable<T>泛型接口。这些实现是在运行时提供给数组的,因此无法被文档生成工具所显示。因此,在Array类的声明语法中不会出现泛型接口,并且没有参考主题来访问只能通过将数组强制转换为泛型接口类型(显式接口实现)才能访问的接口成员。

因此,你的Employee[]实现了IEnumerable<Employee>


15
澄清一下,实现它的不是Array类,而是任何T类型的T[]。 - IS4

6
默认情况下,员工数组实现了 IEnumerable<Employee>IEnumerable 接口。

3

当某些句子需要进行向下转换(downcast)时,就需要进行显式强制类型转换。也就是将一个对象转换为更专业的类型——如果该对象正是这种专业类型的话。

另一方面,向上转换(upcasting)(将一个对象转换为较不专业的类型),永远不需要显式强制类型转换,但你也可以明确地这么做(只是无用的)。

由于数组实现了IEnumerableIEnumerable<T>,在您的代码中进行了向上转换,这意味着您不需要显式转换为IEnumerable<T>


3
我不同意。在某些情况下,需要显式向上转换。例如函数覆盖:void DoStuffs(IEnumerable<T> objects) { ... }void DoStuffs(params T[] objects) { DoStuffs((IEnumerable<T>) objects); } - Orace
2
@Orace 这并不完全是向上转型...这是编译器帮助调用所需重载的方法...你同意吗? ;) 这是一个方法重载解析问题。 - Matías Fidemraizer
@Orace 嗯,这是一个向上转型,但我的意思是你需要显式地进行“转型”以调用所需的重载... - Matías Fidemraizer

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