2009-08-07 14 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実装がオープンジェネリック型の中でクローズドジェネリックメソッドを許可するという事実を指す。私は楽しみのための標準の私自身の実装に取り​​組んでいます、私はそのケースをサポートする必要があるかどうかを把握しようとしています。 :) –

+0

さて、「珍しい」投稿には申し訳ありません。 CLIは、オープンジェネリック型の中でクローズされたジェネリックメソッドを明示的に禁止していません。ジェネリックメソッドとその宣言型、およびネストされたジェネリック型との関係を定義します。 CLIは、部分的に構築された型を禁止し、型をインスタンス化することを禁じているので、メソッドはあまり使われないだろうと思う。 MethodDefSigと他のものについては、それを動的アセンブリに放出し、ディスクから解析するのはどうですか? –

関連する問題