4

次のようなクラスがあります。

public class DropDownControl<T, Key, Value> : BaseControl
    where Key: IComparable
{
    private IEnumerable<T> mEnumerator;
    private Func<T, Key> mGetKey;
    private Func<T, Value> mGetValue;
    private Func<Key, bool> mIsKeyInCollection;

    public DropDownControl(string name, IEnumerable<T> enumerator, Func<T, Key> getKey, Func<T, Value> getValue, Func<Key, bool> isKeyInCollection)
        : base(name)
    {
        mEnumerator = enumerator;
        mGetKey = getKey;
        mGetValue = getValue;

        mIsKeyInCollection = isKeyInCollection;
    }

そして、辞書に便利な機能を追加したいと思います (辞書はすべての操作を効率的にサポートするため)。

しかし問題は、そのようなコンストラクターは Key と Value のみを指定し、T を直接指定しないことですが、T は単なる KeyValuePair です。次のように、このコンストラクター T が KeyValuePair であることをコンパイラーに伝える方法はありますか?

public DropDownControl<KeyValuePair<Key, Value>>(string name, IDictionary<Key, Value> dict) { ... }

現在、回避策として静的な Create 関数を使用していますが、直接コンストラクターの方が良いと思います。

public static DropDownControl<KeyValuePair<DKey, DValue>, DKey, DValue> Create<DKey, DValue>(string name, IDictionary<DKey, DValue> dictionary)
            where DKey: IComparable
        {
            return new DropDownControl<KeyValuePair<DKey, DValue>, DKey, DValue>(name, dictionary, kvp => kvp.Key, kvp => kvp.Value, key => dictionary.ContainsKey(key));
        }
4

2 に答える 2

13

いいえ、基本的に。非ジェネリック クラス (DropDownControl [no <>] など) の静的メソッドは、Create() を呼び出すときに型推論を使用できるはずなので、最善の方法です。

var control = DropDownControl.Create(name, dictionary);

C# 3.0 は、"var" (ここでは大歓迎です) と大幅に改善されたジェネリック型推論規則の両方によって、ここで役立ちます。いくつかの(より一般的な)ケースでは、別の同様のオプションは拡張メソッドですが、辞書から非常に具体的なコントロールを作成するための拡張メソッドはあまり自然に感じられません-非拡張メソッドを使用します.

何かのようなもの:

public static class DropDownControl
{
    public static DropDownControl<KeyValuePair<TKey,TValue>, TKey, TValue>
            Create<TKey,TValue>(IDictionary<TKey, TValue> value, string name)
    where TKey : IComparable
    {
        return new DropDownControl<KeyValuePair<TKey, TValue>, TKey, TValue>
            (name, value, pair => pair.Key, pair => pair.Value,
            key => value.ContainsKey(key)
        );
    }
}

別のオプションは継承ですが、あまり好きではありません...

public class DropDownControl<TKey, TValue> :
    DropDownControl<KeyValuePair<TKey, TValue>, TKey, TValue>
    where TKey : IComparable
{
    public DropDownControl(IDictionary<TKey, TValue> lookup, string name)
        : base(name, lookup, pair => pair.Key, pair => pair.Value,
            key => lookup.ContainsKey(key)) { }
}

これにより複雑さが増し、柔軟性が低下します...私はこれをしません...

全体として、 IDictionary<,> だけで作業したいようです-これを使用するだけでコントロールを単純化し、非辞書の呼び出し元に IDictionary<,> ファサードでラップするように強制できないのでしょうか?

于 2008-10-04T12:47:17.547 に答える