Was genau ist ein “offener generischer Typ” in .NET?

Ich ging durch Asp.Net MVC Lektion und erfuhr, dass für eine Methode, um als eine Aktion für einen Controller zu qualifizieren,

  • Es darf keinen “offenen generischen Typ” haben

Ich verstehe Generika etwas und benutze sie zu einem gewissen Grad, aber:

  • Was ist ein offener generischer Typ in .Net.
  • Gibt es so etwas wie einen geschlossenen generischen Typ ?
  • Open generic type ist ein Begriff, der nicht oft verwendet wird. Was ist damit verwechselt?

Solutions Collecting From Web of "Was genau ist ein “offener generischer Typ” in .NET?"

Die C # -Sprache definiert einen offenen Typ als einen Typ, der entweder ein Typargument oder ein generischer Typ ist, der mit unbekannten Typargumenten definiert ist:

Alle Typen können als offene oder geschlossene Typen klassifiziert werden. Ein offener Typ ist ein Typ, der Typparameter einschließt. Genauer:

  • Ein Typparameter definiert einen offenen Typ.
  • Ein Array-Typ ist nur dann ein offener Typ, wenn sein Elementtyp ein offener Typ ist.
  • Ein konstruierter Typ ist nur dann ein offener Typ, wenn einer oder mehrere seiner Argumenttypen einen offenen Typ haben . Ein konstruierter geschachtelter Typ ist ein offener Typ, wenn und nur wenn einer oder mehrere seiner Typargumente oder die Typargumente seines enthaltenden Typs ein offener Typ sind.

Ein geschlossener Typ ist ein Typ, der kein offener Typ ist.

Daher sind T , List und Dictionary und Dictionary alle offene Typen ( T und U sind Typargumente), während List und Dictionary geschlossene Typen sind .

Es gibt ein verwandtes Konzept: Ein ungebundener generischer Typ ist ein generischer Typ mit nicht spezifizierten Argumenten. Ein nicht gebundener Typ kann nicht in anderen Ausdrücken als typeof() und Sie können ihn nicht instanziieren oder seine Methoden aufrufen. Zum Beispiel sind List<> und Dictionary< ,> ungebundene Typen.

Um die feine Unterscheidung zwischen einem offenen Typ und einem ungebundenen Typ zu verdeutlichen:

 class Program { static void Main() { Test(); } static void Test() { Console.WriteLine(typeof(List)); // Print out the type name } } 

Wenn Sie dieses Snippet ausführen, wird es ausgedruckt

 System.Collections.Generic.List`1[System.Int32] 

Dies ist der CLR-Name für List . Zur Laufzeit ist klar, dass das Argument type System.Int32 . Dies macht List einem gebundenen offenen Typ.

Zur Laufzeit können Sie mit der Methode Type.MakeGenericType mithilfe von Reflection Type.MakeGenericType an nicht spezifizierte Typparameter ungebundener generischer Typen Type.MakeGenericType :

 Type unboundGenericList = typeof(List<>); Type listOfInt = unboundGenericList.MakeGenericType(typeof(int)); if (listOfInt == typeof(List)) Console.WriteLine("Constructed a List type."); 

Sie können prüfen, ob ein Typ ein ungebundener generischer Typ ( generische Typdefinition ) ist, aus dem Sie gebundene Typen mit der Type.IsGenericTypeDefinition Eigenschaft Type.IsGenericTypeDefinition :

 Console.WriteLine(typeof(Dictionary< ,>).IsGenericTypeDefinition); // True Console.WriteLine(typeof(Dictionary).IsGenericTypeDefinition); // False 

Um den ungebundenen Typ zur Laufzeit aus einem konstruierten Typ zu ermitteln, können Sie die Type.GetGenericTypeDefinition Methode verwenden .

 Type listOfInt = typeof(List); Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>) 

Beachten Sie, dass Sie für einen generischen Typ entweder eine vollständig nicht gebundene Typdefinition oder eine vollständig gebundene Definition haben können. Sie können einige Typparameter nicht binden und andere nicht gebunden lassen. Zum Beispiel können Sie Dictionary oder Dictionary< ,string> nicht haben.

Nur um hinzuzufügen:

Dictionary (genauer gesagt Dictionary ) ist immer noch ein offener Typ.

Beispiel:

 void Foo(Dictionary dic) { ... } 

Ein “offener generischer Typ” ist nur ein generischer Typ, für den noch kein Typ angegeben ist (z. B. CargoCrate ). Es wird “geschlossen”, sobald ein konkreter Typ zugewiesen wurde (zB CargoCrate ).

Angenommen, Sie haben Folgendes:

 public class Basket { T[] basketItems; } public class PicnicBlanket { Basket picnicBasket; // Open type here. We don't know what T is. } // Closed type here: T is Food. public class ParkPicnicBlanket : PicnicBlanket { } 

Hier ist der Typ von picnicBasket offen: T ist noch nichts zugewiesen. Wenn du eine konkrete PicnicBlanket mit einem bestimmten Typ erstellst – zum Beispiel indem PicnicBlanket p = new PicnicBlanket() – nennen wir es jetzt geschlossen .

Es gibt drei Arten von generischen Typen. Um es kurz zu machen, in dieser (vereinfachten) Erklärung:

 public class Dictionary : IEnumerable> 
  • Dictionary ist ein unbeschränkter generischer Typ .

  • KeyValuePair ist in diesem Fall ein offener konstruierter generischer Typ . Es hat einige Typparameter, aber sie sind bereits anderswo definiert (in diesem Fall in Dictionary).

  • Dictionary wäre ein geschlossener generischer Typ .