2013-08-15 12 views
9

タイトルのために申し訳ありませんまず、私はもっと良いものを考えることができませんでした...ジェネリック医薬品と違いクラスからオーバーロードされたメソッドを呼び出す - 優先順位の問題

私の問題は、単純なコードサンプルが提示することができます。

public static class Test<T> 
{ 
    public static int GetInt(T source) 
    { 
     return Convert.ToInt32(source); 
    } 
} 

public static class Convert 
{ 
    public static int ToInt32(byte source) 
    { 
     return 30; 
    } 

    public static int ToInt32(object source) 
    { 
     return 10; 
    } 
} 

なぜConsole.WriteLine(Test<byte>.GetInt(20));プリント10、代わりの30していますか?

.NETのジェネリックは、実行時にJITによって解決されるといつも思っていました。なぜ、ジッタが十分にスマートではないのですか?のパラメータタイプに合ったToInt32(byte)メソッドが存在することを確認するには、

この動作により、Convert静的クラスのメソッドは、単純な型のボクシング/アンボクシング操作の結果を呼び出します。

+0

'テスト .GetInt(byte.Parse(「20」))'私は見知らぬ人を見つけるいるだけでなく10を返し、ウォッチウィンドウは、タイプは何にとして、いくつかの手がかりを与えるかもしれないオブジェクト{バイト}であると言いますは進行中です – Sayse

答えて

7

コンパイラは、コンパイル時にどの方法を選択するか決定する必要があります。実行時に選択する2つのオーバーロードのいずれかを決定するコードは生成されません。 GetInt(T source)byte構造体でしか動作しないというC#コンパイラの証拠を提供していないので、コンパイラはもう一方のオーバーロードを選択する必要があります。

また別の見方をすると、ToInt32(object)のオーバーロードを削除すると、プログラムがコンパイルされません。

+0

'byte'メソッド(または一般的に、利用可能な最良のメソッド)を呼び出す方法はありますか? – MarcinJuraszek

+0

真実が唯一の方法であればtypeof(T)== typeof(byte)+ byteへのキャスト – Vitaly

+0

@MarcinJuraszek:ボクシングは本当に問題ですか? – Steven

0

コンパイラは、実行する方法をコンパイル時に決定します。

.method public hidebysig static int32 GetInt(!T source) cil managed 
{ 
    .maxstack 1 
    .locals init (
     [0] int32 CS$1$0000) 
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: box !T 
    L_0007: call int32 ConsoleApplication1.Convert::ToInt32(object) <-- HERE 
    L_000c: stloc.0 
    L_000d: br.s L_000f 
    L_000f: ldloc.0 
    L_0010: ret 
} 

ジョンスキートhereで述べたように、あなたは型付きを提供dynamicを使用して、バイトメソッドへの呼び出しを行うことができます - 私はILコードためリフレクターを通して見ると、これを見つけた

コンパイル時ではなく実行時の情報

public static class Test<T> 
{ 
    public static int GetInt(T source) 
    { 
     dynamic dynamicSource = source; 
     return Convert.ToInt32(dynamicSource); 
    } 
} 
関連する問題