19

私はそれを読んだ:

チームは通常、イニシャライザに他のバリエーションを実装するのに忙しくしています。たとえば、 Dictionary オブジェクトを初期化できるようになりました

しかし、見て:

var Dic = new Dictionary<string,int>{ {"x",3}, {"y",7} };

対。

var Dic = new Dictionary<string,int>{ ["x"]=3, ["y"]=7 };

どこにメリットがあるのか​​わからない。それは同じように見えます。どちらも名前と値のコレクションにすぎません。
彼らは中括弧のペアを角括弧のペアといくつかのコンマに置き換えました

質問:

新しい構文を使用することの付加価値は何ですか? 実世界の例は大歓迎です。

4

4 に答える 4

30

ここでの辞書の主な利点は、一貫性です。ディクショナリでは、初期化は使用法と同じようには見えませんでした。

たとえば、次のことができます。

var dict = new Dictionary<int,string>();
dict[3] = "foo";
dict[42] = "bar";

ただし、初期化構文を使用すると、中かっこを使用する必要がありました。

var dict = new Dictionary<int,string>
{
    {3, "foo"},
    {42, "bar"}
};

新しい C# 6 インデックス初期化構文により、初期化構文がインデックスの使用法とより一貫したものになります。

var dict = new Dictionary<int,string>
{ 
    [3] = "foo",
    [42] = "bar"
};

ただし、より大きな利点は、この構文が他の型を初期化できるという利点も提供することです。インデクサーを持つすべての型は、この構文による初期化を許可します。古いコレクション初期化子は、メソッドを実装IEnumerable<T>して持つ型でのみ機能しますAdd。それはたまたま で動作しましたDictionary<TKey,TValue>が、それはインデックスベースの型で動作したという意味ではありません。

于 2015-01-21T20:37:42.077 に答える
9

最初のケースのコードは、コレクション初期化子の構文を使用しています。コレクション初期化子の構文を使用できるようにするには、クラスは次のことを行う必要があります。

コレクション初期化子:

  1. インターフェイスを実装しIEnumerableます。
  2. アクセス可能なメソッドを定義しますAdd()。(C#6/VS2015からは拡張メソッドかもしれません)

したがって、そのように定義されたクラスは次の構文を使用できます。

public class CollectionInitializable : IEnumerable
{
    public void Add(int value) { ... }
    public void Add(string key, int value) { ... }
    public IEnumerator GetEnumerator() { ... }
}

var obj = new CollectionInitializable
{
    1,
    { "two", 3 },
};

すべてのオブジェクトがIEnumerableadd メソッドである、または add メソッドを持っているわけではないため、その構文を使用できません。


一方、多くのオブジェクトは (設定可能な) インデクサーを定義します。ここで辞書イニシャライザが使用されます。インデクサーを持つことは理にかなっているかもしれませんが、必ずしもそうであるとは限りませんIEnumerable。ディクショナリ初期化子を使用するとIEnumerable、 である必要はなく、メソッドも必要ありませんAdd()。インデクサーのみが必要です。

単一の式でオブジェクトを完全に初期化できることは、一般的に便利です (コンテキストによっては要件になります)。ディクショナリ初期化子構文を使用すると、コレクション初期化子を使用するという厳しい要件がなくても、これを簡単に実行できます。

于 2015-01-21T20:37:05.267 に答える
8

疑わしい機能かもしれませんが、新しい構文では同じものを複数回設定できます。

        private static Dictionary<string, string> test1
        = new Dictionary<string, string>() {
            ["a"] = "b",
            ["a"] = "c"
        };

が許可されています: ここで、キー"a"には値があります"c"

対照的に、

private static Dictionary<string, string> test2
    = new Dictionary<string, string>() {
        { "a","b" },
        { "a","c" },
    };

例外を作成します:

Unbehandelte Ausnahme: System.TypeInitializationException: Der Typeninitialisierer für "ConsoleApplication1.Program" hat eine Ausnahme verursacht. 
---> System.ArgumentException: Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt.
   bei System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   bei System.Collections.Generic.Dictionary``2.Insert(TKey key, TValue value, Boolean add)
   bei System.Collections.Generic.Dictionary``2.Add(TKey key, TValue value)
   bei ConsoleApplication1.Program..cctor() in Program.cs:Zeile 19.
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei ConsoleApplication1.Program.Main(String[] args)
于 2016-02-28T18:54:49.040 に答える
2

それ自体には技術的な利点はありません。これは単なるシンタックス シュガーです (多くの新しい C# 6 機能と同様)。実際、 C# 機能の説明 PDFでは、エレガンスの問題のみが言及されています。

オブジェクトとコレクションの初期化子は、オブジェクトのフィールドとプロパティを宣言的に初期化する場合や、コレクションに要素の初期セットを与える場合に役立ちます。インデクサーを使用して辞書やその他のオブジェクトを初期化するのは、あまり洗練されていません。オブジェクト初期化子に新しい構文を追加して、新しいオブジェクトが持つ任意のインデクサーを介してキーに値を設定できるようにします

于 2015-01-24T09:53:35.043 に答える