96

いくつかの特定のシナリオでは、辞書にそのようなキーがない場合に、キーで辞書の値にアクセスしている間nullではなく、短くて読みやすい方法を使用することが便利であるように見えました。KeyNotFoundException

私が最初に頭に浮かんだのは、拡張メソッドでした。

public static U GetValueByKeyOrNull<T, U>(this Dictionary<T, U> dict, T key)
        where U : class //it's acceptable for me to have this constraint
{
    if (dict.ContainsKey(key))
        return dict[key];
    else 
        //it could be default(U) to use without U class constraint
        //however, I didn't need this.
        return null; 
}

しかし、あなたがこのようなものを書くとき、それは実際にはあまり口頭ではありません:

string.Format("{0}:{1};{2}:{3}",                                                 
              dict.GetValueByKeyOrNull("key1"),
              dict.GetValueByKeyOrNull("key2"),
              dict.GetValueByKeyOrNull("key3"),
              dict.GetValueByKeyOrNull("key4"));

基本構文に近いものを使用する方がはるかに良いと思いますdict["key4"]

private次に、必要な機能を公開する辞書フィールドを持つクラスを作成するというアイデアを思いつきました。

public class MyDictionary<T, U> //here I may add any of interfaces, implemented
                                //by dictionary itself to get an opportunity to,
                                //say, use foreach, etc. and implement them
                                // using the dictionary field.
        where U : class
{
    private Dictionary<T, U> dict;

    public MyDictionary()
    {
        dict = new Dictionary<T, U>();
    }

    public U this[T key]
    {
        get
        {
            if (dict.ContainsKey(key))
                return dict[key];
            else
                return null;
        }
        set
        {
            dict[key] = value;
        }
    }
}

しかし、基本的な動作にわずかな変更を加えるのは少しオーバーヘッドのようです。

Funcもう1つの回避策は、現在のコンテキストで次のようにを定義することです。

Func<string, string> GetDictValueByKeyOrNull = (key) =>
{
    if (dict.ContainsKey(key))
        return dict[key];
    else
        return null;
};

のように利用できますGetDictValueByKeyOrNull("key1")

お願いします、私にもっと良い提案をするか、より良いものを選ぶのを手伝ってくれませんか?

4

7 に答える 7

84

これは、拡張メソッドとして実装された私の個人的なライブラリからの私のソリューションです。辞書インターフェイスから実装され、オプションのデフォルト値を渡すことができるため、投稿しているだけです。

実装

public static TV GetValue<TK, TV>(this IDictionary<TK, TV> dict, TK key, TV defaultValue = default(TV))
{
    TV value;
    return dict.TryGetValue(key, out value) ? value : defaultValue;
}

使用法

 MyDictionary.GetValue("key1");
 MyDictionary.GetValue("key2", -1);
 MyDictionary.GetValue("key3")?.SomeMethod();
于 2015-10-19T20:18:32.047 に答える
36

拡張メソッドでは必要な構文を取得できません。他の人が言っているように、メソッド/演算子をオーバーライドしてその動作を変更することは、一般的には良い考えではありません。できることは、使う名前を短くすることだと思います。

これは、IDictionaryインターフェイスを維持する必要がある場合です。IDictionaryを期待するコードとインターフェースをとっていない場合は、独自のインターフェースを自由に定義でき、[]演算子の動作を変えることは問題ありません。

関数を呼び出すことになったものは何でも、次のように実装する必要があります。

public static U Get<T, U>(this Dictionary<T, U> dict, T key)
    where U : class
{
    U val;
    dict.TryGetValue(key, out val);
    return val;
}

実装の2つと比較して、1つのルックアップを実行するだけです。

于 2013-01-04T16:24:36.643 に答える
19

DictionaryExtensionクラスを追加する

public static class DictionaryExtension
{
    public static TValue GetValueOrDefault<TKey, TValue>
        (   this IDictionary<TKey, TValue> dictionary,TKey key)
    {
        TValue value;
        return dictionary.TryGetValue(key, out value) ? value : default(TValue);
    }
}

また、辞書にキーが見つからない場合は、デフォルト値を返すことができます。

デフォルトはnull、これが参照型の場合です。

_dic.GetValueOrDefault();
于 2017-03-31T05:41:47.550 に答える
7

HybridDictionaryはデフォルトでこれを行うことに注意してください。一般的な型付けは失われますが、null-if-not-found 機能が得られます。

そして、(少なくとも理論的には)値の数が少ない場合にパフォーマンス上の利点が得られると思います。

于 2013-11-17T11:48:32.140 に答える
5

私はこれを使用しないと言って前提としています。このnew場合、キーワードは便利ですが、見つけるのが非常に難しいバグを作成する可能性があります。それ以外は、このクラスを試すことができます。

class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new TValue this[TKey key]
    {
        get
        {
            TValue value;
            return TryGetValue(key, out value) ? value : default(TValue);
        }
        set { base[key] = value; }
    }
}
于 2013-01-04T03:26:25.703 に答える