2009-08-07 119 views
2

有我偶然發現了實現定義的行爲?CLI嵌套泛型類型和泛型方法

這裏是上下文:

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

這裏的行爲。這個單元測試按照書面通過。我的實際問題在「古怪」(如我現在看來)行爲之前被列爲評論。

[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()); 
} 

回答

0

這不是太奇怪了:

//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 

只是比較來自斷言所有組合。

P.S.你錯過了

Assert.AreNotSame(closedTypeOpenMethod, openTypeOpenMethod); 
+0

1)我沒有錯過這種情況(它的參數是相反的,但我有它)。 2)這些檢查都不是在我的崗位的那些後顯着,但我會加入他們還有更多,因爲它們對API重要。 3)你沒有回答我的任何3個問題,都是指一個事實,即ECMA-335的.NET Framework實現允許開放式泛型類型內封閉泛型方法。我的工作我自己的實現爲樂趣的標準,我試圖找出如果我要支持這種情況下,還是不行。 :) – 2009-08-07 23:12:06

+0

好了,比較遺憾的是「不起眼」後。 CLI無處不在顯式禁止在一個開放的泛型類型中關閉泛型方法。它定義了泛型方法與其聲明類型以及嵌套泛型類型之間的關係。僅CLI禁止部分構造類型和實例開放類型,所以我猜的方法不會太多的使用,至少在實例方法。至於MethodDefSig和其他,爲什麼不嘗試將它發射到動態組裝和從磁盤分析? – 2009-08-08 01:21:24