21

ジェネリッククラスのメソッドを呼び出す必要があり、インスタンスの実際の型を気にしないアプリケーションを開発しています。次のJavaコードのようなもの:

public class Item<T>{
  private T item;

  public doSomething(){...}
}

...
public void processItems(Item<?>[] items){
 for(Item<?> item : items)
   item.doSomething();
}

急いでいたときは、呼び出す必要のあるメソッドでインターフェイスを定義し、ジェネリッククラスに実装させることで問題を解決しました。

public interface IItem  
{
   void doSomething();
}

public class Item<T> : IItem {
  private T item;

  public void doSomething(){...}
}

...
public void processItems(IItem[] items)
{
 foreach(IItem item in items)
   item.doSomething();
}

この回避策は問題なく機能しますが、同じ動作を実現するための正しい方法を知りたいと思います。

編集:

processItemsの発信者が実際のタイプを知らないことを参照するのを忘れました。実際のアイデアは、引数として渡された配列processItemsに混合型を含めることができるというものでした。.Netでそのような配列を使用することは不可能であるため、非ジェネリックの基本クラスまたはインターフェイスを使用することが唯一の方法のようです。

4

5 に答える 5

25

これを行う通常の方法は、メソッドをジェネリックにすることです。

public void ProcessItems<T>(Item<T>[] items) {
  foreach(Item<T> item in items)
    item.DoSomething();
}

呼び出し元が型を知っていると仮定すると、型推論は、型を明示的に指定する必要がないことを意味するはずです。例えば:

Item<int> items = new Item<int>(); // And then populate...
processor.ProcessItems(items);

そうは言っても、型に依存しない操作を指定する非ジェネリックインターフェイスを作成することも役立つ場合があります。それはあなたの正確なユースケースに大きく依存します。

于 2009-02-09T11:24:34.983 に答える
3

パラメータなしでいくつかのメソッドを呼び出したいだけだと思います...そのためのコントラクトが既にあります: Action

public void processItems(IEnumerable<Action> actions)
{
  foreach(Action t in actions)
    t();
}

クライアント:

List<Animal> zoo = GetZoo();
List<Action> thingsToDo = new List<Action>();
//
thingsToDo.AddRange(zoo
  .OfType<Elephant>()
  .Select<Elephant, Action>(e => e.Trumpet));
thingsToDo.AddRange(zoo
  .OfType<Lion>()
  .Select<Lion, Action>(l => l.Roar));
thingsToDo.AddRange(zoo
  .OfType<Monkey>()
  .Select<Monkey, Action>(m => m.ThrowPoo));
//
processItems(thingsToDo);
于 2009-02-09T14:53:11.473 に答える
1

.NETジェネリック実装で型パラメーターを省略できる方法はありません。これは仕様によるものです。実際、これは、型消去ベースの実装のため、Javaでのみ実現できます。

基本の非ジェネリックインターフェイス(think IEnumerable<T>and IEnumerable)のみを使用できます。

于 2009-02-09T11:22:45.020 に答える
0

さらにジョンの投稿へ。メソッドをジェネリック (テンプレート) にすると、この種の機能の要件が無効になります (<?> を使用)。いつでも型をジェネリック クラス/関数にフィードできます。必要な型がわからない場合は、問題のあるメソッド/クラスをジェネリックにすることもできます...最終的には、ユーザーは呼び出し時に型を提供する必要があります。コードをコンパイルできるようにするために、そのような関数またはジェネリッククラスを使用します...そうしないと、コンパイラエラーが発生します。

于 2009-02-09T11:34:33.150 に答える
0

次のような構造を持っているJavaからのものを移植することになると、私は同じ問題に苦労してきました

if (o instanceof Collection<?>) doSoemthing((Collection<?>)o);

幸いなことに、ジェネリック ICollection は非ジェネリック ICollection でもあることがわかり、その中の要素を純粋なオブジェクトとして扱う必要がある場合でも、それは可能です。

if (o is ICollection) DoSomething((ICollection)o);

そうすれば、コレクション内の要素の実際のタイプは気にしないので、ここで得られるのはオブジェクトだけです。ここでの注意: コレクションがプリミティブ型 (int や byte など) を保持していた場合、オートボクシングが開始され、パフォーマンスが低下する可能性があります。

于 2009-12-30T16:57:35.850 に答える