2012-12-09 18 views
6

さまざまなジェネリック型に応じて異なる結果を得るには、メソッドのオーバーロードを使用します。それは動作しません。私のコードはそれをはっきりと示します。ジェネリック型のオーバーロードエラー

static class Helper 
{ 

    public static bool Can(int i) 
    { 
     return true; 
    } 

    public static bool Can(Object o) 
    { 
     return false; 
    } 
} 

class My<T> 
{ 
    public static bool can = Helper.Can(default(T)); 
} 

Console.WriteLine(Helper.Can(default(int)));//True,it is OK 

Console.WriteLine(My<int>.can);//false?? why the overload doesn't work 
Console.WriteLine(My<Object>.can);//false 

なぜMy<int>呼び出しHelper.Can(オブジェクトO)ではなくHelper.Canは、(i int型)?

答えて

4

このようには機能しません。

オーバーロードは完全にコンパイル時に解決されます。ジェネリック型パラメータは実行時に解決されます。
Tintであることをコンパイラが認識していないため、コードは常にCan(Object)を呼び出します。

+0

素晴らしい。ありがとうございました – zilong

+0

「実行時にジェネリック型のパラメータが解決されました」という記述には賛成できません。その場合、コンパイラは 'List 'からint項目を取得できないことをコンパイル時に知ることができませんでした。コンパイル時に未解決と見なされるものは、ジェネリッククラス内のジェネリック型パラメータの出現です。 –

+0

@ O.R.Mapper:ジェネリッククラス内での意味です。 – SLaks

1

それは少し冗長ですが、あなたはリフレクションを使って、欲しいものを達成できる:

class My<T> 
{ 
    static bool doStuff() 
    { 
     var rightMehod = typeof(Helper).GetMethods().Where(p => 
      { 
       if (!p.Name.Equals("Can")) 
        return false; 

       if (!p.ReturnType.Equals(typeof(bool))) 
        return false; 

       if (p.GetParameters().Length != 1) 
        return false; 

       var par = p.GetParameters().First(); 
       return par.ParameterType.Equals(typeof(T)); 
      }).FirstOrDefault(); 

     if (rightMehod == null) 
     { 
      return Helper.Can(default(T)); 
     } 
     else 
     { 
      return (bool)rightMehod.Invoke(null, new object[] { default(T) }); 
     } 
    } 

    public static bool can = doStuff(); 
} 

この方法では、当然のことながら

My<string>.can == false 
My<int>.can == true 
My<object>.can == false 

、追加的な工芸品のビットを持つ(とジェネリック型の使用法)では、さまざまな状況でそのスニペットを広範囲に再利用することができます。

追加の注釈が1つあります。この例では、具体的な例として直接型比較を使用しています。継承された型を扱う場合、これは適切に動作しないことに注意してください(もちろん、いくつかの追加のあいまいさもあります)。

3

一般的に、それはコンパイル時にオブジェクトに解決されますが、あなたはダイナミックキーワード使用して実行時まで待つようにそれを伝えることができます:だから

class My<T> 
{ 
    public static bool can = CanWithDynamic(); 

    private static bool CanWithDynamic() { 
     dynamic runtimeT = default(T); 
     return Helper.Can(runtimeT); 
} 

を、これはあなたがしようとしている何のために動作します適切なオーバーロードが呼び出されます。しかし、実行時に解決されるものと同様に、それに関連するパフォーマンスコストがあります。多分そうではないかもしれませんが、このメソッドを頻繁に呼び出すと、影響が出る可能性があります。