Es scheint, dass in .NET "array of enum" kein stark typisiertes Konzept ist. Es wird davon ausgegangen, dass MyEnum[]
nicht nur IEnumerable<MyEnum>
, sondern auch IEnumerable<YourEnum>
implementiert. (Ich habe es auch zuerst nicht geglaubt.)
Wenn ich also eine Liste nach allem durchsuche, was IEnumerable<T>
implementiert, bekomme ich die T[]
s und die List<T>
s und die iteratorgenerierte IEnumerable<T>
s, aber ich bekomme auch die SomethingElse[]
s, die ich nicht will.
Was ist der einfachste Weg herauszufinden, ob eine gegebene Type
(wie bei IsAssignableFrom oben) oder eine gegebene Instanz (wie bei OfType<T>
oben) wirklich und wirklich implementiert, sagen wir, IEnumerable<DayOfWeek>
?
Ich gab Mr. Skeet das grüne Häkchen, aber sobald ich seinen Code in Visual Studio bekam, schlug ReSharper eine etwas kompaktere Version vor. Verwenden Sie die von Ihnen bevorzugte Version.
%Vor%Ich glaube, das liegt im Wesentlichen an Abschnitt 8.7 von ECMA 335 .
Grundsätzlich betrachten wir die zuweisbare Beziehung zwischen den beiden Array-of-enum-Typen. Soweit ich das beurteilen kann, gilt 8.7.2:
Ein Standorttyp T ist kompatibel mit einem Standorttyp U, wenn und nur wenn einer der folgenden Punkte zutrifft.
- T und U sind keine verwalteten Zeigertypen und T ist kompatibel mit U gemäß der Definition in §8.7.1.
Also schauen wir uns 8.7.1 an und finden Punkt 5:
T ist ein nullbasiertes Rang-1-Array V [], und U ist ein nullbasiertes Rang-1-Array W [], und V ist Array-Element-kompatibel mit W .
Nun interessiert uns, ob die beiden Enum-Typen eine Array-Element-kompatible-mit Beziehung haben ... Das führt dann zu:
Ein Signaturtyp T ist arrayelementkompatibel - mit einem Signaturtyp U genau dann, wenn T den zugrunde liegenden Typ V hat und U den zugrunde liegenden Typ W hat und entweder:
- V ist kompatibel mit W; oder
- V und W haben denselben reduzierten Typ.
Nun ist der zugrunde liegende Typ einer Enumeration definiert:
Der zugrunde liegende Typ eines Typs T ist der folgende:
- Wenn T ein Aufzählungstyp ist, dann ist der zugrunde liegende Typ der zugrunde liegende Typ, der in der Aufzählung definiert ist.
- [irrelevant für uns]
Also im Fall von, sagen wir:
%Vor% Die zugrunde liegenden Typen von beiden sind int
.
Nun können wir zu unserer array-element-compatible-with Definition zurückkehren und sehen, dass sowohl V als auch W int
sind. Ein Typ ist kompatibel mit selbst aufgrund des ersten Aufzählungszeichens von 8.7.1:
Ein Signaturtyp T ist kompatibel mit einem Signaturtyp U, wenn und nur wenn mindestens einer der folgenden Werte zutrifft.
- T ist identisch mit U.
Daher sind die Arrays kompatibel.
Sie sind auch mit einem Array des zugrunde liegenden Typs kompatibel:
%Vor% Beachten Sie, dass x
hier als object
deklariert werden muss, um den C # -Compiler davon zu überzeugen, dass diese möglicherweise legal ist - ansonsten folgt sie den Regeln der C # -Sprache, die nicht ganz korrekt sind so verzeihend ...
Nun zu Ihrer zweiten Frage:
Was ist der einfachste Weg herauszufinden, ob ein bestimmter Typ (wie bei IsAssignableFrom oben) oder eine bestimmte Instanz (wie bei OfType oben) wirklich und wirklich implementiert, sagen wir IEnumerable?
Sie könnten nur Sonderfälle Arrays, da sie sich ein wenig seltsam verhalten. Ehrlich gesagt ist das wahrscheinlich der einfachste Ansatz. Ich habe versucht, mit Type.GetInterfaceMap
, aber das gibt auch ein Problem:
Nicht behandelte Ausnahme: System.ArgumentException: Schnittstelle maps für generische interf Asse in Arrays können nicht abgerufen werden.
(Ja, der Tippfehler am Ende ist wirklich in der Fehlermeldung. Kann nicht gestört werden, ein Connect-Problem für diese zu richten, obwohl ...)
Ich vermute stark, dass Spezialgehäuse der Weg nach vorne ist ... zum Beispiel unter der Annahme, dass Sie wissen , dass es sich um einen Werttyp handelt (die Kovarianz von Referenzarrays ist eine separate Angelegenheit). ..)
%Vor%