2009-06-02 27 views
3

第二の方法やキャストの多くに頼ることなく次の操作を行うための良い、一般的な、方法はあります - 私はできるだけ軽量APIを維持したいし、それがOO-賢明な私にはOKらしい:メソッドの汎用インターフェイスのオーバーロード

class Foo 
{ 
    public T Bar<T>() where T: IAlpha 
    { 
    /* blahblahblah */ 
    } 

    public T Bar<T>() where T: IBeta 
    { 
    /* blahblahblah */ 
    } 
} 

interface IAlpha 
{ 
    string x {set;} 
} 

interface IBeta 
{ 
    string y {set;} 
} 

ありがとう

答えて

7

戻り値だけでメソッドをオーバーロードすることはできません(汎用かどうか)。さらに、オブジェクトがIAlphaIBetaの両方を実装できるので、オーバーロードを使用することはできませんので、Barへの呼び出しを解決することは不可能です。

public class AlphaBeta : IAlpha, IBeta 
{ 
    string x {set;} 
    string y {set;} 
} 

// too ambiguous 
AlphaBeta parkingLot = myFoo.Bar<AlphaBeta>(); 

方法が唯一残念ながら、あなたの最善の解決策は、以下の一般的なソリューションを使用することで、戻り値の型

class Gar 
{ 
    public string Foo() 
    { 
     return ""; 
    } 

    public int Foo() 
    { 
     return 0; 
    } 
} 

によって異なりますので下記も、動作しません。コマンドパターンがここでうまく役立つかもしれません。

public class Foo 
{ 
    private readonly static Dictionary<Type, Command> factories = 
     new Dictionary<Type, Command>(); 

    static Foo() 
    { 
     factories.Add(typeof(IAlpha), new AlphaCreationCommand()); 
     factories.Add(typeof(IBeta), new BetaCreationCommand()); 
    } 

    public T Bar<T>() 
    { 
     if (factories.ContainsKey(typeof(T))) 
     { 
      return (T) factories[typeof(T)].Execute(); 
     } 
     throw new TypeNotSupportedException(typeof(T)); 
    } 
} 

// use it like this 
IAlpha alphaInstance = myFoo.Bar<IAlpha>(); 
IBeta betaInstance = myFoo.Bar<IBeta>(); 

明示的に(自分の山かっこ内)のタイプを宣言しなくても、それを呼び出すことができますバーを実装する別の方法は、outパラメータを使用することです。私はそれを避けるだろう、しかし、100%のパラメータが悪い設計の臭いを管理していたから。

public void Bar<T>(out T returnValue) 
{ 
    if (factories.ContainsKey(typeof(T))) 
    { 
     returnValue = (T) factories[typeof(T)].Execute(); 
     return; 
    } 
    throw new TypeNotSupportedException(typeof(T)); 
} 

// call it like this 
// T is inferred from the parameter type 
IAlpha alphaInstance; 
IBeta betaInstance; 
myFoo.Bar(out alphaInstance); 
myFoo.Bar(out betaInstance); 

私はCommandAlphaCreationCommandBetaCreationCommand、およびTypeNotSupportedExceptionを除外しました。それらの実装は、かなり自明でなければなりません。

コマンドの代わりにFuncを使用することもできますが、コードベースの拡大に合わせてすべてのインスタンス化コードをFooに実装する必要があります。

+0

両方を実装するタイプでは特にコンパイルされません。しかし、他のすべての型についてコンパイルします(あなたの言葉は、これによってコンパイルされないことを意味します)。 –

+0

私は、戻り値の型だけでメソッドのオーバーロードがコンパイルされるのを認識していません。例を挙げることができれば、答えを編集して修正することができます。 –

1

これはいかがですか?

class Foo 
{ 
    public void Bar<T>(Action<T> @return) where T: IAlpha 
    { 
    @return(new AlphaImpl()); 
    } 

    public void Bar<T>(Action<T> @return) where T: IBeta 
    { 
    @return(new BetaImpl()); 
    } 
} 

interface IAlpha 
{ 
    string x {set;} 
} 

interface IBeta 
{ 
    string y {set;} 
} 
関連する問題