Umwandlung des Arrays in IEnumerable <T>

74

Angenommen, Sie haben eine Grundklasse Employeeals solche:

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

Dann habe ich (in einer separaten Klasse) die folgenden Codefragmente (ich glaube, ich verstehe alle bis auf die letzten):

Ich glaube, dass das folgende Codefragment funktioniert, weil der Array-Initilierer ein Array von Employee-Objekten erstellt, die vom selben Typ sind wie die Workforce-Variable, der zugewiesen wird.

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

Ich habe dann das folgende Codefragment. Ich glaube, dass dies funktioniert, weil die Array- EmployeeObjektimplizität eine Implementierung der Array () -Klasse ist, die implementiert wird IEnumerable. Daher glaube ich, dass das Array aus diesem Grund IEnumerable zugewiesen werden kann.

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

Dann habe ich dieses Codefragment:

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

Ich bin nicht sicher, warum dieses Codefragment funktioniert? IEnumerable<Employee>erbt von IEnumerableder GetEnumerator()Methode (und überschreibt sie (oder überschreibt sie?) ), aber sollte ich deshalb keine Besetzung benötigen, damit die oben genannten als solche funktionieren:

//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" } };

Es scheint, dass das Array implizit von einem Typ IEnumerableauf " down" übertragen wird , IEnumerable<Employee>aber ich dachte immer, wenn Sie einen Typ in etwas Spezifischeres konvertieren müssen, benötigen Sie einen expliziten Cast.

Vielleicht fehlt mir hier etwas Einfaches in meinem Verständnis, aber kann mir bitte jemand bei meinem Verständnis helfen?

Vielen Dank.

Gefährlich
quelle
3
@Aliostad: Es ist direkt unter dem workforceThreeFragment.
Heinzi

Antworten:

110

Aus der Dokumentation :

In .NET Framework Version 2.0 implementiert die Array - Klasse , die System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>und System.Collections.Generic.IEnumerable<T>generische Schnittstellen. Die Implementierungen werden Arrays zur Laufzeit zur Verfügung gestellt und sind daher für die Tools zum Erstellen von Dokumentationen nicht sichtbar. Infolgedessen werden die generischen Schnittstellen nicht in der Deklarationssyntax für die Array-Klasse angezeigt, und es gibt keine Referenzthemen für Schnittstellenmitglieder, auf die nur zugegriffen werden kann, indem ein Array in den generischen Schnittstellentyp umgewandelt wird (explizite Schnittstellenimplementierungen).

So Ihre Employee[]Geräte IEnumerable<Employee>.

Heinzi
quelle
11
Zur Verdeutlichung ist es nicht die Array-Klasse, die es implementiert, sondern T [] eines T.
IllidanS4 unterstützt Monica
4

Das Array of Employees implementiert standardmäßig IEnumerable<Employee>auchIEnumerable

Dennis Traub
quelle
3

Explizite Besetzung ist erforderlich, wenn ein Satz herabgestuft werden muss . Das heißt, ein Objekt wird in einen spezialisierteren Typ umgewandelt - wenn das Objekt von einem solchen spezialisierten Typ ist -.

Auf der anderen Seite benötigt Upcasting (Casting auf einen weniger spezialisierten Typ) niemals eine explizite Besetzung, aber Sie können dies explizit tun (es ist einfach nutzlos).

Da Array IEnumerableund implementiert IEnumerable<T>, führen Sie einen Upcast in Ihrem Code durch, was bedeutet, dass Sie nicht explizit in umwandeln müssen IEnumerable<T>.

Matías Fidemraizer
quelle
3
Ich stimme nicht zu. In einigen Fällen benötigen Sie einen expliziten Upcast. Als Beispiel für eine Funktionsüberschreibung: void DoStuffs (IEnumerable <T> -Objekte) {...} void DoStuffs (params T [] -Objekte) {DoStuffs ((IEnumerable <T>) -Objekte); }
Orace
2
@Orace Dies ist nicht gerade ein Upcast ... Es ist eine Compiler-Hilfe, um die gewünschte Überladung aufzurufen ... sind Sie damit einverstanden? ;) Es handelt sich um ein Problem mit der Auflösung von Methodenüberlastungen.
Matías Fidemraizer
@Orace Nun, es ist ein Upcast, aber ich meine, dass Sie die explizite "Besetzung" benötigen, um die gewünschte Überladung aufzurufen ...
Matías Fidemraizer