2017-02-16 11 views
3

キーが値オブジェクトのプロパティである辞書を作成しようとしています。しかし、私は辞書のaddメソッドでvalueオブジェクトを構築したいと思います。中間変数を使用せずにこれを行う方法はありますか?キーが値のプロパティである辞書に要素を追加する

たとえば、次のようにしたいと思いますが、必要に応じてキー値を使用することはできません。

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>{ 
    {someComplexObject.Key, new SomeComplexObject {Key = 1, Name = "FooBar"}, 
    {someComplexObject.Key, new SomeComplexObject {Key = 2, Name = "FizzBang"} 
}; 

が、私はそれをこの醜い方法で行う必要があります:

Dictionary<int,SomeComplexObject> dict = new Dicionary<int,SomeComplexObject>(); 
SomeComplexObject value1 = new SomeComplexObject{Key=1,Name = "FooBar"}; 
dict.Add(value1.Key,value1); 
SomeComplexObject value2 = new SomeComplexObject{Key=2,Name = "FizzBang"}; 
dict.Add(value.Key,value2); 

を私は、キーについては特に求めていないですので、これは How to use an object's identity as key for Dictionary<K,V>

と同じ質問だとは思いませんメソッドのパラメータリストの後半になるまでオブジェクトが作成されていないときに、オブジェクトプロパティにアクセスする方法があるかどうかを確認します。

+0

コメント[チャットでアーカイブ](http://chat.stackoverflow.com/rooms/136085/discussion-on-question-by-automatic-add-element-to-dictionary-where-key-is-prope) 。 –

答えて

2

元の質問は私にはあまり明確ではないようですが、コメントの議論の後、他の人は正しいと思っています。私が選んだ重複はおそらく正しいものではないでしょう。私はまた、あなたが必要とする答えを得るための機会を潜在的に遅らせるか、あるいは排除することさえも、自分の答えを提案する能力を他の人が妨げたので、答えを提供する義務を感じる。

私はまた、拡張メソッド(コメントで提案されているように)が本当にあなたがここで必要としているとは思っていません。私。使用したいディクショナリの値の型ごとに新しい拡張メソッドを記述する必要があります。これは、一般的な解決策を求める要点を否定します。

代わりに、Dictionary<TKey, TValue>タイプをサブクラス化して独自のカスタム動作を追加したいと思うようです。これを汎用の方法で一度だけ行うことができます。これにより、このように使用する必要があると予想される各タイプのデリゲートを提供できます。次のようになります

:あなたがいるように見えるよう

class Data 
{ 
    public int Key { get; } 
    public string Name { get; } 

    public Data(int key, string name) 
    { 
     Key = key; 
     Name = name; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     KeyExtractorDictionary<int, Data> dictionary = 
      new KeyExtractorDictionary<int, Data>(d => d.Key) 
      { 
       new Data(1, "FooBar"), 
       new Data(2, "FizzBang") 
      }; 
    } 
} 

(私が代わりにTの、値型のタイプとしてDataを使用:

class KeyExtractorDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
{ 
    private readonly Func<TValue, TKey> _extractor; 

    public KeyExtractorDictionary(Func<TValue, TKey> extractor) 
    { 
     _extractor = extractor; 
    } 

    public void Add(TValue value) 
    { 
     Add(_extractor(value), value); 
    } 
} 

あなたはこのような何か、それを使用しますあなたの質問には、型名をジェネリック型パラメータと混同しないようにするために使用しています)。

このようにして、tこのタイプの辞書にどのように多くの異なるタイプを使用したいのかに関わらず、彼は一度クラス分けします。次に、辞書の現在の値型に適したキーコンストラクタをクラスコンストラクタに渡すことができます。

このようにすると、C#のコレクション初期化構文を利用することもできます。新しいタイプはAdd()メソッドで各ディクショナリエントリの値だけを使用するため、コンパイラはコレクション初期化子を正しい呼び出しに変換して各オブジェクトを辞書に追加します。

これは、依然としてキー値だけでオブジェクトを取り出すことができる辞書を可能にします(カスタム比較者は、あなたが探しているのと同じキーを持つ値型のインスタンスを必要とします)。オブジェクトを追加するときにキーを明示的に指定する必要がないという懸念、一般性と再利用の問題

0

あなたは低侵襲性である、拡張メソッドを試すことができます。

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item) 
{ 
    dictionary.Add(item.Key, item); 
} 

しかし、実際にこれを正しく行うには、あなたはまた、Keyプロパティなしタイプに対してあなたを保護するためのインタフェースを必要とする:

public interface ItemWithKey<TKey> 
{ 
    TKey Key { get; } 
} 

public static void AddByKey<TKey, T>(this Dictionary<TKey, T> dictionary, T item) 
    where T : ItemWithKey<TKey> 
{ 
    dictionary.Add(item.Key, item); 
} 

私の手にはコンパイラがありません。このコードはテストできませんので、軽微なエラーが入っている可能性があります。さもなければ、私はあなたがすでに持っている醜い作業コードに行くことをお勧めします。

関連する問題