2

私が書いているジェネリックメソッドに問題があります。次の署名があります。

public static ThingCollection<T> GetThings<T>(...) where T : Thing

いくつかのクラスがあります。Thing を継承する ThingA、ThingB、および ThingC。メソッドでこのようなコードを使用できるようにしたいと考えています。

var things = new ThingCollection<T>();

if (typeof(T) == typeof(Thing))
  foreach (var item in someCollection)
    things.Add((T)new Thing(...));
else if (typeof(T) == typeof(ThingA))
  foreach (var item in someCollection)
    things.Add((T)new ThingA(...));
else if (typeof(T) == typeof(ThingB))
  foreach (var item in someCollection)
    things.Add((T)new ThingB(...));
else if (typeof(T) == typeof(ThingC))
  foreach (var item in someCollection)
    things.Add((T)new ThingC(...));
else
  throw new Exception("Cannot return things of type " + typeof(T).ToString());

return things;

問題は、新しいオブジェクトをキャストしないと、最適なオーバーロードされたメソッドの一致に無効な引数エラーが発生することです。上記のように T キャストを追加することは、新しい Thing() では問題ありませんが、他の新しい呼び出しでは型 'ThingA' を 'T' に変換できません。Intellisense は T が Thing であることを示していますが、他のオブジェクトを Thing から継承しているため、Thing にキャストできない理由がわかりません。

おそらく、これは私がやろうとしていることを行う正しい方法ではありません。私は正しい軌道に乗っていますか?おそらくいくつかの小さなニュアンスが欠けているのでしょうか、それともまったく別のことをすべきでしょうか?

4

4 に答える 4

7

あなたがそのコードで何をしようとしているのかわかりません。

モノから派生した任意の型のクラスを追加できるモノのコレクションを作成したい場合、ThingCollection は Typename を持つべきではありません: 具体的な型のコレクションであるはずです。

たとえば、次のように ThingCollection を実装します。

public class ThingCollection : List<Thing> {}

今、あなたはできる

ThingCollection tc = new ThingCollection();
tc.Add(new ThingA());
tc.Add(new ThingB());
tc.Add(new ThingC());

もちろん、ThingA、ThingB、および ThingC が Thing を継承していると仮定します。

または、GetThings() を使用して Thing の派生型をフィルター処理したい、つまり、GetThings() の呼び出しで ThingCollection を返すようにしたい場合もあります。

于 2008-11-13T09:59:52.413 に答える
3

主に私が思うに、このコード スニペットは設計が悪いと思います。「ThingD」クラスを追加する場合、明確な動作のために、コードの別の部分を変更する必要があります。次のようなものを使用する必要があります。

public static ThingCollection<T> GetThings<T>(...) where T : Thing, new()
...
...
T item = new T();
item.Something = Whatever();

または、「ICloneable」インターフェイス int Thing クラスを実装できます。

于 2008-11-13T09:41:47.020 に答える
3

このコードは、T を使用する前にその型をテストしようとするため、Liskov の置換原則に違反しています。

これを回避するには、辞書/戦略の組み合わせまたは訪問者パターンを使用できます。

T が ThingB の場合、キャスト (T)ThingA は無効であるため、コードは実際には間違っています。

于 2008-11-13T09:44:37.793 に答える
2

それらが共通のインターフェイス (IThing) を使用している場合は、それにキャストできるはずです。

于 2008-11-13T09:38:28.213 に答える