:
のコードは、方法によってXamarinからです。
C#では、配列初期化子の中括弧は、コレクションクラスのコンストラクタで動作するように一般化されています。
いずれのクラスも、System.Collections.IEnumerable
を実装し、1つ以上のAdd()
メソッドを持つクラスをサポートします。 Eric Lippert has a good post about this type of "pattern matching" in C#:コンパイラがここで行っているのは、継承とインターフェイスの実装に基づいてクラスの機能が認識される従来型の厳密に型指定されたOOPではなく、「duck typing」と呼ばれるものです。 C#はいくつかの場所でこれを行います。私が知らなかったその記事にはたくさんのものがあります。
public class Foo : List<String>
{
public void Add(int n)
{
base.Add(n.ToString());
}
public void Add(DateTime dt, double x)
{
base.Add($"{dt.ToShortDateString()} {x}");
}
}
そして、これはコンパイル:
は
var f = new Foo();
f.Add(0);
f.Add(1);
f.Add(2)
f.Add("Zanzibar");
f.Add(DateTime.Now, 3.7);
あなたはこれらとかなり奇妙なゲームをプレイすることができます。このためにシンタックスシュガーです
var f = new Foo { 0, 1, 2, "Zanzibar", { DateTime.Now, 3.7 } };
。私はそれが良い考えであるかどうか分からない(実際にはdoを知っている - それはできません)。私は、コレクションの初期化子でオプションを定義できるコマンドラインパーサークラスを作成しました。 Add
の数多くのオーバーロードがあり、さまざまなパラメータリストがあり、その多くは汎用的です。コンパイラが推論できるものはすべて、公正なゲームです。
また、これを減らすことなく、機能の悪用のポイントに戻ることができます。
は何を見ていると、それはあなたがクラス自体が既に作成された非アサインメンバーのコレクション初期化子を行うことができます同じ初期化子構文を拡張したものです:
public class Bar
{
public Foo Foo { get; } = new Foo();
}
そして今... 。
var b = new Bar { Foo = { 0, "Beringia" } };
{ 0, "Beringia" }
Bar
が自身のために作成したFoo
インスタンスのコレクション初期化子です。それは、このために糖衣構文です:あなたはそれをそのように見たときに、構文糖の初期化子の使用にFoo.Add()
の過負荷を解決するための
var b = new Bar();
b.Foo.Add(0);
b.Foo.Add("Beringia");
コンパイラの意欲が理にかなっています。私はそれを行うことができるのはすばらしいことだと思っていますが、彼らが選んだ構文に100%満足しているわけではありません。代入演算子が赤いニシンであることがわかった場合、他のものもそうです。
しかし、私は構文アービターではありません。それはおそらくすべての関係者に最適です。
最後に、これは、オブジェクト初期化子で動作します:
public class Baz
{
public String Name { get; set; }
}
public class Bar
{
public Foo Foo { get; } = new Foo { 1000 };
public Baz Baz { get; } = new Baz { Name = "Initial name" };
}
だから... ...実際に変身
var b = new Bar { Foo = { 0, "Beringia" }, Baz = { Name = "Arbitrary" } };
...
var b = new Bar();
b.Foo.Add(0);
b.Foo.Add("Beringia");
b.Baz.Name = "Arbitrary";
我々は初期化できませんBar.Baz
はセッターがないので、プロパティを初期化できるのと同じようにプロパティを初期化できますems in Foo
。実際のコンストラクタにアタッチされた別のオブジェクトイニシャライザによって既に初期化されていても、それは当てはまります。
コレクションイニシャライザは、累積しています:Bar.Foo
は、{ "1000", "0", "Beringia" }
の3つのアイテムを持ちます。
中括弧は代入文の列の省略形またはAdd()
オーバーロード呼び出しのように考えると、すべてがフォーカスに合っています。
しかし、左辺値が実際に割り当てられていない場合には、等号が不安定であることに同意します。ここでボーナス
public static class HoldMyBeerAndWatchThis
{
public static IEnumerable<int> Select(Func<String, String> f)
{
yield return f("foo").Length;
}
}
...
var x = from s in HoldMyBeerAndWatchThis select s;
あなたが仕事へselect
のために必要なすべてがあるという事ます」から選択するにはSelect
という名前のメソッドがあり、のようなものが返されますIEnumerable
は、foreach
のthe linked article(感謝します!Eric!)の@EricLippertの発言に概説されており、Func<T,T>
パラメータをとります。
私はちょうど先日もこれを発見しました。私はそれがどのように動作するかを正確に分離することはできませんでした。 – DLeh
[イニシャライザのMSDNドキュメント](https://msdn.microsoft.com/en-us/library/bb384062.aspx)によれば、この初期化子を使用しているときにコンパイルが繰り返し「追加」を呼び出すようです。この構文を変数宣言で直接使用することはできません。例えば'IList children = {" childfoo "、" childbar "}'はコンパイルされません –
@ stephen.vakil:時には、あなたはほとんど可能です。 '' children' {'childfoo"、 "childbar"}; ' – recursive