2009-11-24 9 views
8

これは前にどこかで回答されていると確信していますが、どこでも見つけることができませんでした。いくつかのジェネリックの達人が助けてくれることを願っています。アクションを伴う汎用メソッド<T>パラメータ

public interface IAnimal{} 
public class Orangutan:IAnimal{} 

public void ValidateUsing<T>(Action<T> action) where T : IAnimal 
{ 
    Orangutan orangutan = new Orangutan(); 
    action(orangutan); //Compile error 1 

    //This doesn't work either: 
    IAnimal animal = new Orangutan(); 
    action(animal); //Compile error 2 
} 
  1. 引数の型 'オランウータンは' タイプのパラメーターに割り当てない 'T'
  2. 引数の型 'IAnimalは 'T'

編集パラメータのタイプに割り当て可能ではありません。ベースYuriyと他の提案のでは、次のようなキャストを行うことができます:

public void ValidateUsing<T>(Action<T> action) where T : IAnimal 
{ 
    Orangutan orangutan = new Orangutan(); 
    action((T)(IAnimal)orangutan); 

    //This doesn't work either: 
    IAnimal animal = new Orangutan(); 
    action((T)animal); 
} 
ValidateUsing(Foo); 

残念なことに、fooは次のようになります場合:

private void Foo(Orangutan obj) 
{ 
    //Do something 
} 

私は

をValidateUsing呼び出すときに、明示的に型を指定する必要があり、私がやってみたかった事は、このようValidateUsingメソッドを呼び出しました
ValidateUsing<Orangutan>(Foo); 

答えて

6

は、なぜあなたはOrangutanをインスタンス化していますか?

public void ValidateUsing<T>(Action<T> action) where T : IAnimal, new() 
{ 
    T animal = new T(); 
    action(animal); //Compile error 2 

あなたは一般的なパラメータを再利用する場合には、すべてのタイプの問題を持っていないだろう...あなたのコードが動作しない理由に関しては今

、あなたが言っていることはすべて、ということですタイプTIAnimalに由来します。ただしGiraffeOrangutanと同じように簡単にできるので、TのパラメータにOrangutanまたはIAnimalを割り当てることはできません。

+0

おかげさまで、オランウータンを例として使用しました。おそらく悪い。私は任意のIAnimalでアクションを呼び出せるようにしたい。 "実際の"コードでは、IAnimalはクラスのプライベートフィールドとして格納されます。だから、私は何もインスタンス化していません。 –

2

これを試してください。

Orangutan orangutan = new Orangutan(); 
Action<IAnimal> castedAction = action as Action<IAnimal>; 
castedAction(orangutan); 
+0

ありがとうございました!もし私が十分な評判を持っていれば、私はあなたの答えをアップアップします。 –

2

次のように変更します。あなたはどのIAnimalを受け入れることになっている場合

Orangutan orangutan = new Orangutan(); 
action((T)(IAnimal)orangutan); 


IAnimal animal = new Orangutan(); 
action((T)animal); 
+0

こんにちは、これはとてもうまく動作します。それは私を道の一部にしてくれる(編集を参照)。ありがとう! –

0
public interface IAnimal { } 
public class Orangutan : IAnimal { } 

public void ValidateUsing<T>(Action<T> action) where T : IAnimal 
{ 
    Orangutan orangutan = new Orangutan(); 
    action((T)(orangutan as IAnimal)); // needs to be cast as IAnimal 

    //This doesn't work either: 
    IAnimal animal = new Orangutan(); 
    action((T)animal); // needs to be cast as T 
} 

また、インターフェイスが違いを生むようです。あなたは抽象クラス動物、代わりのインタフェースを持っていた場合は、これを行うことができます:

public abstract class Animal { } 
public class Orangutan : Animal { } 

public void ValidateUsing<T>(Action<T> action) where T : Animal 
{ 
    Orangutan orangutan = new Orangutan(); 
    action(orangutan as T); 

    //This doesn't work either: 
    Animal animal = new Orangutan(); 
    action(animal as T); 
} 
+0

こんにちはクライミング、詳細な答えをありがとう。私は抽象クラスよりもはるかに頻繁にインターフェイスを使用する傾向があります(構成と継承の両方を優先します)が、抽象クラスで動作することは興味深いことです。 –

4

事があり、Tは、道でIAnimalを実装何らかの種類を表していること。

あなたは、アクションタイプのものであってもよいひいてはタイプTのパラメータを取る必要があることを宣言しているので、あなたがエラーを取得action(new Organatum())をコンパイルしようとするので、のは、Fishを言わせて - あなたはOrganatumをキャストすることはできませんFishに、あなたはできますか?

IAnimalインターフェイスを実装するタイプのパラメータを取るアクションをトリガする場合は、ジェネリックを忘れてAction<IAnimal>を使用します。

HTH。

関連する問題