2

インターフェイスの型から、基本クラスから拡張されたそのインターフェイスの実装にマップするディクショナリを実装する小さなクラスがあります。残念ながら、抽象基本クラスはインターフェイスを実装していないため、一度辞書に入ると、2 つを関連付ける方法はないようです。このクラスには、オブジェクトを BaseClass として格納することに依存する別のメソッドがあります (実際、私のクラスのほとんどはそれに依存しています。ディクショナリへのゲッターは多少便利です)。

private readonly Dictionary<Type, BaseClass> dictionary;

public void Add<T>(BaseClass base)
{
    if (!(base is T))  // How to get rid of this check?
    {
        throw new ArgumentException("base does not implement " + typeof(T).Name);
    }

    this.dictionary.Add(typeof(T), base);
}

public T Get<T>()
{
    BaseClass base;
    this.dictionary.TryGetValue(typeof(T), out base);
    return (T)(object)base;  // How to get rid of (object) cast?
}

(ベースは T) チェック、オブジェクトへのキャスト、またはその両方を削除するために使用できる巧妙な制約はありますか?

参考までに、クラスのセットアップは次のとおりです。

class BaseClass { }
interface IThing { }
class MyClass : BaseClass, IThing { }

dict.Add<IThing>(new MyClass());
IThing myClass = dict.Get<IThing>();
4

2 に答える 2

1

探しているコンパイル時の強制を取得する唯一の方法は、追加される派生型のコンパイル型の知識がある場合です。

たとえば、追加するクラスの型パラメーターも指定する場合、クラスがインターフェイスの型パラメーターを実装することを制約できます。

    public void Add<TInterface, TClass>(TClass @base)
        where TClass : BaseClass, TInterface {
        this.dictionary.Add(typeof(TInterface), @base);
    }

だからあなたはこれを行うことができます:

    MyClass ok = new MyClass();
    dict.Add<IThing, MyClass>(ok);

しかし、これではありません:

    class MyClassNotIThing : BaseClass { }

    MyClassNotIThing notOk = new MyClassNotIThing();
    dict.Add<IThing, MyClassNotIThing>(notOk);

それとは別に、ジェネリック制約は、既知の型 (つまりBaseClass) がジェネリック型パラメーターから継承されることを制約する手段を提供しません。

于 2013-07-12T01:42:04.367 に答える