4

このような初期化構文を使用するには:

var contacts = new ContactList
{
    { "Dan", "dan.tao@email.com" },
    { "Eric", "ceo@google.com" }
};

...私の理解では、私のContactListタイプは2つのパラメーターを受け取るメソッドを定義する必要があります。Addstring

public void Add(string name, string email);

これについて私が少し混乱しているのは、{ }初期化構文が読み取り専用または固定サイズのコレクションを作成するときに最も役立つように見えることです。結局のところ、それは配列の初期化構文を模倣することを意図していますよね?(OK、配列は読み取り専用ではありませんが、固定サイズです。)そして当然、コンパイル時にコレクションのコンテンツ(少なくとも要素の数)がわかっている場合にのみ使用できます。

したがって、このコレクション初期化構文を使用するための主な要件(Addメソッドを持ち、したがって可変コレクションを持つ)は、それが最も役立つ一般的なケースと矛盾しているように思われます。

この問題については、C#設計チームほど多くのことを考えていないと確信しています。この構文には、通常の使用シナリオとより適切に一致するさまざまなルールがあった可能性があるようです。

私はここで基地から離れていますか?固定サイズのコレクションを初期化するために構文を使用したいという願望は、{ }私が思うほど一般的ではありませんか?私が単に考えていないこの構文の要件の定式化に影響を与えた可能性のある他の要因は何ですか?

4

9 に答える 9

10

この問題について、C# 設計チームほど深く考えたことはないと思います。この構文には、その典型的な使用シナリオとうまくかみ合う別のルールがあった可能性があるようです。

あなたの分析は非常に優れています。重要な問題は、上記のステートメントの最後の 3 つの単語です。実際の典型的な使用シナリオは何ですか?

コレクション初期化子の典型的な使用シナリオに動機付けられた設計上の目標は、コレクション初期化子をクエリ内包表記に埋め込んだり、式ツリーに変換したりできるように、式構文既存のコレクション型の初期化を可能にすることでした。

他のすべてのシナリオは優先度が低かった。この機能は、LINQ を機能させるのに役立つため、まったく存在します。

C# 3 コンパイラ チームは、Visual Studio / .NET のそのリリースの「長い柱」でした。どのチームよりもスケジュールの中で最も多くの作業日がありました。つまり、毎日遅れると、製品が遅れることになります。私たちは皆さんのために高品質の製品を時間通りに出荷したいと考えていました.完璧は善の敵です. はい、この機能は少し不格好であり、必要なすべてのことを行うわけではありませんが、ほとんど機能しない一連の不変のコレクション型で機能させるよりも、LINQ で確実にテストしてテストすることが重要でした。ある。_

フレームワークの種類がまだ進化している間に、この機能が最初から言語に組み込まれていたとしたら、状況は異なっていただろうと確信しています。このサイトの他の場所で説明したように、一度だけ書き込み、何度も読み込める固定サイズの値の配列が欲しいと思っています。一連の状態を提供して任意の不変コレクションを初期化するための共通パターンを定義するとよいでしょう。コレクション初期化子の構文がそのようなことに理想的であることは間違いありません。

そのような機能は、潜在的な将来の仮説言語バージョンのリストに含まれていますが、リストの上位にはありません。言い換えれば、イミュータブルなコレクションの初期化のためにシンタックス シュガーについて考えすぎる前に、まず async/await を取得しましょう。

于 2011-01-14T00:41:09.920 に答える
3

これは、初期化ステートメントが CLR の省略形であるためです。バイトコードにコンパイルされると、定義した Add メソッドが呼び出されます。

したがって、この初期化ステートメントは実際には「ファーストクラス」の機能ではないという主張をすることができます。これは、IL に対応するものがないためです。しかし、これは私たちが使用する多くのもの、たとえば "using" ステートメントに当てはまります。

于 2011-01-13T14:46:44.063 に答える
2

これは、後付けされたためです。コレクションを取得するコンストラクターを使用する方がはるかに理にかなっていることに同意しますが、既存のコレクションクラスのすべてがこれを実装しているわけではなく、変更は(1)既存のすべてのコレクションで機能し、(2)既存のクラスを変更しないでください。仕方。

それは妥協です。

于 2011-01-13T14:55:20.090 に答える
2

主な理由はシンタックスシュガーです。

初期化構文は、C#でのプログラミングの記述を少し簡単にするだけです。それは実際には言語に表現力を追加しません。

イニシャライザがメソッドを必要としなかった場合、Add()それは現在とは大きく異なる機能になります。基本的に、それはC#がどのように機能するかではありません。一般的なコレクションを作成するための文字通りの形式はありません。

于 2011-01-13T14:46:04.750 に答える
2

厳密に言えば、答えではありませんが、コレクションの初期化子の設計にどのようなことが影響したかを知りたい場合は、おそらくこれが興味深いと思います。

于 2011-01-13T14:46:08.743 に答える
1

不変型(コレクションと通常型の両方)の初期化構文が欲しいです。これは、に似た構文を使用した特別なコンストラクターのオーバーロードで実装できると思いますparams

たとえば、次のようなものです。

MyClass(initializer KeyValuePair<K,V>[] initialValues)

しかし残念ながら、C#チームはまだそのようなことを実装していませんでした:(

したがって、次のような回避策を使用する必要があります

MyClass(new KeyValuePair<K,V>[]{...})

今のところ

于 2011-01-13T14:56:48.430 に答える
1

メソッドでない場合、初期化構文は何を使用する必要がありますAddか?コレクションのコンストラクターが実行され、コレクションが完全に作成された後、初期化構文は「run」になります。コレクションが作成された後、コレクションにアイテムを追加する何らかの方法が必要です。

読み取り専用コレクションを初期化する場合は、コンストラクターで実行します(T[] items引数などを取得します)

于 2011-01-13T14:46:09.310 に答える
1

コレクション初期化子はであるため、フィールド初期化子や LINQ クエリなど、式のみが有効な場合に使用できます。これは、それらの存在を非常に便利にします。

また、中括弧で囲まれた { }種類の初期化は、固定サイズのコレクションのようなにおいがすると思いますが、それは単なる構文の選択です。

于 2011-01-13T15:07:27.197 に答える
1

私が理解している限り、コレクション初期化子の構文は、特別なトリックを含まない単なる構文糖衣です。これは、Linq クエリ内でのコレクションの初期化をサポートするために部分的に設計されました。

from a in somewhere
select new {
   Something = a.Something
   Collection = new List<object>() {
      a.Item1,
      a.Item2,
      ...
   }
}

以前はこれをインラインで行う方法がなく、ケースの後に行う必要があり、面倒でした。

于 2011-01-13T14:49:36.493 に答える