2013-07-18 10 views
13

Nach this Antwort bei Stackoverflow, ist der generische Typ in C# zur Laufzeit aufgelöst.Wann ist der generische Typ in C# aufgelöst?

Allerdings, nach this Antwort, in C# ist der generische Typ bei Kompilierungszeit aufgelöst.

Was fehlt mir hier?

Mit anderen Worten, ist der Typ T zur Kompilierzeit oder Laufzeit aufgelöst?

Update:

auf Oded Antwort Basierend In einem Fall wie diesem, wo der Typ eine geschlossene Betontyp ist (was bedeutet, dass es bei der Kompilierung aufgelöst werden würde)

class Program 
{ 
    static void Main() 
    { 
     var t = new Test<int>(); 
    } 
} 

public class Test<T> 
{ 
} 

wird die MSIL haben das Äquivalent von

class Program 
{ 
    static void Main() 
    { 
     var t = new Test(); 
    } 
} 

public class Test<int> 
{   
} 
+3

Diese beiden Posts, auf die Sie verlinken, beschreiben unterschiedliche Konzepte. – JerKimball

+2

Welchen Teil davon aus der geposteten Antwort in dem von Ihnen angegebenen Link verstehen Sie nicht? Nein; das ist grundsätzlich unmöglich. Der springende Punkt von Generics ist, dass sie Arten der Kompilierung erstellen. Sie versuchen, einen Typ zu erstellen, der zur Kompilierzeit unbekannt ist. Sie können es jedoch mit Reflektion tun. (typeof (MyClass <>). MakeGenericType (myType)) ' – MethodMan

+0

Ich vermute, dass Sie nach einem' Wie Reflection' suchen Beispiel – MethodMan

Antwort

21

Das Problem ist, dass die Frage nicht gut gestellt ist. Zwei Personen beanspruchen gegenteilige Dinge: Diese Typen werden zur Laufzeit "aufgelöst" und diese Typen werden zur Kompilierungszeit "aufgelöst".

Da sie sich widersprechen, müssen sie beide durch "aufgelöst" etwas anderes bedeuten.

Ich weiß nicht, was es bedeutet, dass ein Typ "aufgelöst" wird. Ich weiß aber was Überladung Auflösung ist. Auf die Frage, ein Überlastung Auflösung Problem zu lösen, die nicht dynamic beteiligt sind, bestimmt der C# -Compiler, die bei der Kompilierung, basierend zu nennen Überlastung der Kompilierung Informationen über den generischen Typen. So zum Beispiel, wenn Sie:

static void Main() 
{ 
    var d = new D(); 
    var p = new P<D>(); 
    p.N(d);//Displays In class B 
} 


class B 
{ 
    public void M()// Note, not virtual 
    { 
     Console.WriteLine("In class B"); 
    } 
} 

class D : B 
{ 
    public new void M()// new, not overload 
    { 
     Console.WriteLine("In class D"); 
    } 
} 

class P<T> where T : B 
{ 
    public void N(T t) 
    { 
     t.M(); 
    } 
} 

N immer ruft B.Mauch wenn P<T> als P<D> instanziiert wird. Warum? Da die Überladungsauflösung Problem, das bestimmt, was die Bedeutung von t.M muß gelöst werden, wenn P<T>.N wird zusammengestellt, und zu diesem Zeitpunkt die beste der Compiler weiß, ist, dass tB sein muss, so dass es wählt B.M.

Wenn Sie das nicht mit "gelöst" meinen, dann klären Sie die Frage.

+0

Zeigt das Beispiel eine Überladungsauflösung oder -bindung? Während das Binden eine Überladungsauflösung erfordert, haben die beiden einzigen Verfahren, die mit dem Namen "M" identische Signaturen haben, nur eine "Überladungsauflösung", mit der nur ein Kandidat arbeiten könnte. Ich denke, ein besseres Beispiel für "Überladungsauflösung" könnte "statisches bool" sein. Vergleichen (T p1, T p2) wo T: klasse {return p1 == p2;} ... Vergleichen ("5", 5.ToString()) '. Da der Compiler nicht wissen kann, dass 'T' vom Typ' String' ist, kann er nicht wissen, dass er 'String'-vs-' String' overload von '==' verwenden soll, anstatt einen Referenzvergleich durchzuführen. – supercat

+0

BTW, ist der Referenz-Vergleich von '==' eine Überladung, oder ist es eine andere Art von Compiler Magie? Eine Überladung von '==', die Parameter vom Typ 'Object' verwendet hat, würde erlauben, zwei beliebige Typen zu vergleichen, aber der C#' == 'Operator funktioniert nicht so. Sein Verhalten scheint sich von allem zu unterscheiden, was mit einer normalen Überladungsauflösung erreicht werden könnte. – supercat

+0

@supercat: Gute Frage. Es verwendet tatsächlich eine normale Überladungsauflösung des Operators mit einigen kleinen Änderungen. Zuerst werden Ausdrücke der Form "x == null", "null! = X" usw. behandelt. Dann erfolgt die Überladungsauflösung normal. Dann gibt es einen Post-Resolution-Validierungsschritt. Wenn die Überladungsauflösung den Operator "object == object" auswählt und einer oder beide Operanden nicht vom Referenztyp sind, wird eine Fehlerbedingung ausgelöst. (Diese kurze Skizze beschreibt nicht alle Feinheiten; siehe die Spezifikation für Details.) –

12

Sie sind die Konzepte der open and closed generic types fehlt.

Im Wesentlichen besteht ein geschlossener generischer Typ darin, dass Sie tatsächlich vorhandene Typen für einen generischen Parameter/s angeben (oder sie werden vom Compiler abgeleitet). Zum Beispiel:

Nullable<int> nulInt; 

Eine offene gattungsgemäßen Art ist ein, wo ein oder mehrere generischer Typ zur Laufzeit bestimmt werden soll (so die Nullable<T> Klasse ist ein Beispiel).

+0

Ah, durn it - Sie haben mich dazu geschlagen. :) – JerKimball

1
  1. die erste Antwort ist etwa Methode
  2. Parameter
  3. und die zweite ist etwa generische Typparameter

das ist, was du verpasst.

genauer: 1. C# wird standardmäßig statisch eingegeben, so dass Sie bei der Übergabe von Parametern den am besten passenden Typ und die Methode erhalten. (Siehe auch die Antwort zu "dynamischen" Parametern.) 2. Das Setzen eines generischen Typparameters über die C# -Syntax erfolgt über statische Typen. Um es durch Nachdenken zu setzen, geht es um etwas anderes.

etwas anderes: "in .NET" jeder Typ hat eine Initialisierung Phase bei der ersten Benutzung zur Laufzeit. (Siehe statische Felder und statischen Konstruktor)

so: Alle Typen sind zur Laufzeit initialisiert, aber statische Typen verwendet werden (oder dynamisch ...) zur Compile-Zeit das ist, wenn sie sein müssen "aufgelöst ".

1

Offene Typen (myclass<T>) existieren nicht Laufzeit. Zur Laufzeit können jedoch nicht gebundene Typen existieren (myclass<>). Um einen ungebundenen Typ zur Laufzeit aufzulösen, müssen Sie den Operator typeof verwenden.

Mit anderen Worten, wenn der Operator typeof nicht verwendet wird, werden generische Typen zum Zeitpunkt der Kompilierung geschlossen.

Verwandte Themen