2009-08-07 5 views
2

Bin ich auf implementierungsdefiniertes Verhalten gestoßen? HierCLI verschachtelte generische Typen und generische Methoden

ist der Kontext:

public class GenericClass<T> 
{ 
    public class NestedGenericClass<U> 
    { 
     public void GenericMethod<K>() 
     { 
     } 
    } 
} 

Hier ist das Verhalten. Dieser Komponententest läuft wie beschrieben ab. Meine tatsächlichen Fragen werden als Kommentar vor dem "verrückten" (wie es mir jetzt scheint) Verhalten aufgeführt.

[TestMethod] 
public void TestNestedGenericMethod() 
{ 
    Type openType = typeof(GenericClass<>.NestedGenericClass<>); 
    Type closedType = typeof(GenericClass<bool>.NestedGenericClass<int>); 
    /* Note there is absolutely no representation of the following as a [unique] type, via the 
    * typeof operator or the Reflection API, even though the metadata TypeSpec signature 
    * should in theory be able to reference it. This is the original reason I wrote these 
    * tests. 
    * Type partiallyOpenType = typeof(GenericClass<bool>.NestedGenericClass<>); 
    */ 

    MethodInfo openTypeOpenMethod = openType.GetMethod("GenericMethod"); 
    MethodInfo closedTypeOpenMethod = closedType.GetMethod("GenericMethod"); 
    MethodInfo closedTypeClosedMethod = closedTypeOpenMethod.MakeGenericMethod(typeof(long)); 

    Assert.IsNotNull(openTypeOpenMethod); 
    Assert.IsNotNull(closedTypeOpenMethod); 
    Assert.IsNotNull(closedTypeClosedMethod); 

    Assert.AreNotSame(openTypeOpenMethod, closedTypeOpenMethod); 
    Assert.AreNotSame(openTypeOpenMethod, closedTypeClosedMethod); 
    Assert.AreNotSame(closedTypeOpenMethod, closedTypeClosedMethod); 

    /* What on earth?! 
    * 1. Is the following covered in the CLI spec and/or is it implementation-defined? 
    * 2. Is there any potential use of this behavior (inside the runtime itself OR outside)? 
    * 3. Will I ever hit a MethodDefSig (§23.2.1)/MethodRefSig (§23.2.2)/MethodSpecSig (§23.2.15) that resolves to this? 
    */ 
    MethodInfo openTypeClosedMethod = openTypeOpenMethod.MakeGenericMethod(typeof(long)); 
    Assert.IsNotNull(openTypeClosedMethod); 
    Assert.AreNotSame(openTypeClosedMethod, openTypeOpenMethod); 
    Assert.AreNotSame(openTypeClosedMethod, closedTypeOpenMethod); 
    Assert.AreNotSame(openTypeClosedMethod, closedTypeClosedMethod); 

    Assert.AreSame(closedTypeOpenMethod, closedTypeClosedMethod.GetGenericMethodDefinition()); 
    Assert.AreSame(openTypeOpenMethod, openTypeClosedMethod.GetGenericMethodDefinition()); 
} 

Antwort

0

Das ist nicht so seltsam:

//void GenericClass<>.NestedGenericClass<>.GenericMethod<Int64>() 
openTypeClosedMethod.ContainsGenericParameters = true 
openTypeClosedMethod.IsGenericMethodDefinition = false 

//void GenericClass<>.NestedGenericClass<>.GenericMethod<K>() 
openTypeOpenMethod.ContainsGenericParameters = true 
openTypeOpenMethod.IsGenericMethodDefinition = true 

//void GenericClass<bool>.NestedGenericClass<int>.GenericMethod<K>() 
closedTypeOpenMethod.ContainsGenericParameters = true 
closedTypeOpenMethod.IsGenericMethodDefinition = true 

//void GenericClass<bool>.NestedGenericClass<int>.GenericMethod<Int64>() 
closedTypeClosedMethod.ContainsGenericParameters = false 
closedTypeClosedMethod.IsGenericMethodDefinition = false 

MethodInfo closedGeneratedMethod = closedTypeClosedMethod.GetGenericMethodDefinition(); 
MethodInfo openGeneratedMethod = openTypeClosedMethod.GetGenericMethodDefinition(); 

//void GenericClass<bool>.NestedGenericClass<int>.GenericMethod<K>() 
closedGeneratedMethod.ContainsGenericParameters = true 
closedGeneratedMethod.IsGenericMethodDefinition = true 

//void GenericClass<>.NestedGenericClass<>.GenericMethod<K>() 
openGeneratedMethod.ContainsGenericParameters = true 
openGeneratedMethod.IsGenericMethodDefinition = true 

einfach alle Kombinationen vergleichen von behauptet.

P.S. Sie verpasst

Assert.AreNotSame(closedTypeOpenMethod, openTypeOpenMethod); 
+0

1) Ich habe diesen Fall nicht vermisst (es ist Parameter umgekehrt, aber ich habe es). 2) Keine dieser Prüfungen ist bemerkenswert nach denen in meinem Beitrag, aber ich werde sie hinzufügen und mehr, weil sie für die API wichtig sind. 3) Sie haben keine meiner 3 Fragen beantwortet, die alle auf die Tatsache verweisen, dass die .NET Framework-Implementierung von ECMA-335 eine geschlossene generische Methode innerhalb eines offenen generischen Typs ermöglicht. Ich arbeite an meiner eigenen Implementierung des Standards für Spaß, und ich versuche herauszufinden, ob ich diesen Fall unterstützen muss oder nicht. :) –

+0

Okay, Entschuldigung für den 'unauffälligen' Beitrag. Das CLI verbietet explizit keine geschlossenen generischen Methoden innerhalb eines offenen generischen Typs. Es definiert Beziehungen zwischen einer generischen Methode und ihrem Deklarationstyp sowie verschachtelten generischen Typen. Die CLI verbietet nur teilweise konstruierte Typen und instanziiert offene Typen, also denke ich, dass die Methode nicht von großem Nutzen wäre, zumindest für Methoden. Versuchen Sie MethodDefSig und andere nicht, es auf eine dynamische Assembly zu verteilen und von Festplatte zu analysieren? –