17

基本的に、私はこのようなものが欲しいです:

Dictionary<object, string> dict = new Dictionary<object, string>();
dict.Add(null, "Nothing");
dict.Add(1, "One");

これを可能にする基本クラスライブラリに組み込まれているものはありますか?上記のコードは、nullキーを追加すると、実行時に例外をスローします。

4

7 に答える 7

11

nullの使用を避けて、同じことを行う特別なシングルトン値クラスを作成することができます。例えば:

public sealed class Nothing
{ 
  public static readonly Nothing Value = new Nothing(); 
  private Nothing() {}
}

Dictionary<object, string> dict = new Dictionary<object, string>();
dict.add(Nothing.Value, "Nothing");
dict.add(1, "One");

コレクションをより強く型付けする場合、このアプローチは機能しません。たとえば、キーを文字列にしたい場合などです。文字列は封印されているため、文字列から継承してnullの代わりに「特別な値」を作成することはできません。あなたの選択肢はもう少し複雑になります。あなたは出来る:

  1. 「空」/「null」の場合を表す特別な定数値を作成します。一種のハッキーで、間違いなく混乱への道です。ディクショナリが特定の実装クラスに対して完全にプライベートであり、キーを変換する方法の知識がいたるところに広がらないように、いくつかのEncode / Decodeユーティリティメソッドを記述できる場合、これは実行可能なアプローチになる可能性があります。
  2. nullの場合を除いて、Dictionary<>インスタンスに内部的に委任するIDictionaryの独自の実装を作成します。これは、nullキーが例外をスローする必要があるというIDictionary<>インターフェイスの文書化された期待に違反します。しかし、それがあなたの本当の問題を解決する唯一の方法であるならば、あなたはそれで逃げることができるかもしれません。これは、辞書インスタンスを所有して作成した場合にのみ機能します。
  3. 辞書に「null」キーを保存せずに問題を解決する方法を見つけてください。たとえば、辞書にnullキーを入力せず、それを処理するための特別な場合のロジックを用意することを検討してください。キーはハッシュ可能であり、基盤となる実装で機能するように比較可能である必要があります。そのため、通常、nullは禁止されています。

余談ですが、辞書のキーには本当にキーが必要objectですか?これにより、Equals()を比較の基礎として評価することを意図した場合に、参照の同等性が使用されるため、微妙なバグが発生する可能性があります。

于 2009-12-16T18:57:51.450 に答える
4

これはどう?

public class NullableDictionnary<T1, T2> : Dictionary<T1, T2>
{
    T2 null_value;

    public T2 this[T1 key]
    {
        get
        {
            if (key == null)
            { return null_value; }
            return base[key];
        }
        set
        {
            if (key == null)
            { null_value = value; }
            else
            { base[key] = value; }
        }
    }
}
于 2009-12-16T19:08:48.730 に答える
1

NameValueCollectionはnullキーを取ることができますが、IDictionaryを実装していません。ただし、DictionaryBaseから派生して、nullを次のような組み込みのものに置き換えるだけのAdd / Remove/Indexersなどを提供するのは非常に簡単です。

class MyDictionary : DictionaryBase {
    private readonly object nullKey = new object();

    void Add(object key, string value) {
       if ( key == null ) { key = nullKey; }
       .. call base methods
    }

}
于 2009-12-16T19:00:42.070 に答える
1

辞書の別の実装は必要ありません。

ここで私の答えを見てください: https ://stackoverflow.com/a/22261282/212272

辞書を強く入力したままにすることもできます。

var dict = new Dictionary<NullObject<int?>, string>();
dict[1] = "one int";
dict[null] = "null int";

Assert.AreEqual("one int", dict[1]);
Assert.AreEqual("null int", dict[null]);
于 2014-03-07T21:50:35.077 に答える
0

キーは文字通りNULLである必要がありますか?コレクションのキーはインデックスとして機能します。コレクション内のインデックスにNULLを設定することは、私にはあまり意味がありません。

たぶん、新しいクラスを作成します


public class ObjectEntry
{
    public object objRef;
    public string desc;

    public ObjectEntry(object objectReference)
    {
        objRef = objectReference;
        if (objRef = null) {desc = "Nothing";}
        else {desc = objRef.Description;} //or whatever info you can get from a proper objRef value
    }
}

newObj = new ObjectEntry(null);
dict.add(newObj, newObj.desc);
于 2009-12-16T19:10:38.123 に答える
0

たとえば、ValueTupleをキーのラッパーとして使用できます。

Dictionary<ValueTuple<string?>, string>
于 2021-09-12T02:40:18.713 に答える
-1

あなたがやろうとしていることをより明確にする、よりクリーンな(私にとって)解決策を作るためのjestroの答えのわずかなバリエーション。明らかに、これは必要に応じて拡張できます。しかし、あなたは絵を手に入れます、ただラッパーを作ってください。

public class NullDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    private TValue _default;
    public new TValue this[TKey key]
    {
        get { 
            if(key == null)
            {
                return _default;
            }
            return _decorated[key];
        }
    }
    private Dictionary<TKey, TValue> _decorated;
    public NullDictionary( Dictionary<TKey,TValue> decorate, TValue defaultValue = default)
    {
        _decorated = decorate;
        _default = defaultValue;
    }    

}
于 2020-05-13T16:04:08.787 に答える