R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

Link

Author

Contact

History

Accessories

書庫

オブジェクトの初期化

C#3.0 では、オブジェクトを生成する際の初期化も簡潔に書けることができます。

例えば、以下のようなコードがあったとします。


class MyClass {
  public string Name;
  public int Age;
}


上記のクラスからオブジェクトを生成する時、以下のように書く必要がありました。


MyClass x = new MyClass();
x.Name = "R・田中一郎";
x.Age = 18;


また、初期化用のコンストラクタを設けることで、初期化を簡潔に書くこともできます。


class MyClass {
  public string Name;
  public int Age;
  public MyClass() {}
  public MyClass(string name, int age) {
    this.Name = name;
    this.Age = age;
  }
}

MyClass x = new MyClass("R・田中一郎", 18);


しかし、当然のことながら初期化用のコンストラクタを持っていなければ、この書き方はできません。

C#3.0 では、上記の

良いところ取り

の書き方ができるようです。


class MyClass {
  public string Name;
  public int Age;
}

MyClass x = new MyClass{ Name = "R・田中一郎", Age = 18 };


上記 1 行は、最初のサンプルと同じ意味を持ちます。
ここまでは、わかりやすくて純粋に素晴らしいと思ったのですが、ちょっとわかりにくいように感じたのがコレクションの初期化です。


List<int> age = new List<int> { 18, 18, 18 };


コレクションの初期化も配列のように書けるようになっています。そう考えればわかりやすいのですが、コレクションのアイテムを追加するのは、Add() メソッドを使って以下のように書く訳です。


List<int> age = new List<int>();
age.Add(18);
age.Add(18);
age.Add(18);


上記の書き方と同様に考えると、以下のように書く方が自然に思えるのですが・・・


List<int> age = new List<int>{ Add(18), Add(18), Add(18) }; // これは間違った書き方ですよ!!(念のため)


コレクションのイニシャライザは「Add だよー」という指定がどこかでできたりするのでしょうかね?

投稿日時 : 2007年6月29日 14:06

Feedback

# re: オブジェクトの初期化 2007/06/29 14:18 επιστημη

List<int> のコンストラクタに IEnumerable<int> を与えることができて、
{ 18, 18, 18 } が IEnumerable<int> とみなされるってことじゃねーのかしらん?
つまりは
new List<int>(new int[] { 18, 18, 18 }) の略記、と。

# re: オブジェクトの初期化 2007/06/29 14:20 囚人

試してないですけど
List<int> age = new List<int>{ Item[0] = 18, Item[1] = 18, Item[2] = 18 };
はどうかな?

# re: オブジェクトの初期化 2007/06/29 14:27 片桐

んー、VBな頭脳の私の感覚としては、NameもAgeもプロパティだけど、Addはメソッドだからだめなんじゃないかと単純に思いました。<単細胞すぎ(笑)

なので、囚人さんのコードだとオブジェクトのプロパティに対して処理をしようとしているのだから出来そうな気がせでもないのですが、配列を「何個でつくるよ」という部分の解釈をうまくコンパイラが引き出せるかどうかにかかってる気がします。

# re: オブジェクトの初期化 2007/06/29 14:50 ぽぴ王子

>> 片桐さん
> 配列を「何個でつくるよ」という部分の解釈
が、まさにえぴさんのコードなんじゃないのかなと。
田中さんのコード的に言えば

List<int> age = new List<int>();
age.AddRange(new int[] { 18, 18, 18 });

か?
Add を繰り返してるんじゃない。IEnumeratable<int> を<del>ママレンジ</del> AddRange してるんだ!ということなのかしらん。
Ω ΩΩ<なんだってー!!

new int[] ~のくだりで既にコンパイル時に要素数が決まっているわけで、だからあんまり気にすることはないんじゃないのかニャーとか鳴いてみるテスト。

> MyClass x = new MyClass{ Name = "R・田中一郎", Age = 18 };

このコードは VB っぽくていいですね。嫌いじゃない。
(使ったことはないし、たぶん使わないけど)

# re: オブジェクトの初期化 2007/06/29 15:19 まどか

#VBだけど
http://www.microsoft.com/japan/msdn/vs05/vbasic/vb9overview.aspx#vb9overview_topic4
によると、「Add持つものなら」と書かれていますね。

匿名型は、ComboBoxのDatasourceに対するカスタムメンバクラスの定義が不要になるのかな?

Dim ComboList = New {New {.Text = "なし", .Value = 0}, New {.Text = "あり", .Value = 1}}
With Combo1
.DataSource = ComboList
.DisplayMember = "Text"
.ValueMember = "Value"
End With
とか。

#VBも{}がメジャーな記号になるようですね。

# re: オブジェクトの初期化 2007/06/29 15:29 επιστημη

> Add を繰り返してるんじゃない。IEnumeratable<int> を<del>ママレンジ</del>
> AddRange してるんだ!ということなのかしらん。

IEnumerable/IEnumerator には”個数”を返すインタフェースがありません。
実装はどうなってっか知らんけど、IEnumerator.MoveNext() が true である間
Addしてますね。

> new int[] ~のくだりで既にコンパイル時に要素数が決まっているわけで、だからあんまり
> 気にすることはないんじゃないのかニャーとか鳴いてみるテスト。

ニャー。

コンストラクタにせよAddRangeにせよ T[] を引数とするものはありません。
したがって、たとえ配列を与えても IEnumearble<T> だと看做しています。
ってことは、「何個でつくるよ」という部分の解釈を"していない"ことになるっす。

# re: オブジェクトの初期化 2007/06/29 18:19 青柳 臣一

C# 3.0 Specification の Collection Initializers
http://msdn2.microsoft.com/en-us/library/ms364047(vs.80).aspx#cs3spec_topic5

ここに書いてありますが、collection initializer は ICollection<T>.Add(T) を順番に呼び出すだけですね。なので、対象となる型は ICollection<T> を実装していないとダメですし、Add 以外で初期化したいということもできません。
想像以上に泥臭い仕様ですが、汎用的にするにはこのくらいにしないとダメだったんでしょうね。

# re: オブジェクトの初期化 2007/06/29 21:48 επιστημη

ふむ、直接 IEnumerable<T> を引数とするコンストラクタによって
初期化しないのはナゼなんだろう。

- コンストラクタをinterfaceに定義できない
- デシリアライズのため、引数を持たないデフォルト・コンストラクタが必要

とかなんとか、そんな理由かしら。

# re: オブジェクトの初期化 2007/06/30 11:37 ぽぴ王子

あ、ちょっと難しそうな話題になっちゃったから家に帰ってゆっくりコメントしなきゃ…と思っていたら翌日になっていた罠。

> IEnumerable/IEnumerator には”個数”を返すインタフェースがありません。

あーそうか。配列を食わせたところで、それは配列としてではなく「よくわかんないけどIEnumerableなリスト」として処理されてるんですね。
一晩寝かせたら理解力がアップした!カレー最高!(関係ない)
ということで
> コンパイル時に要素数が決まっているわけ
は間違いであると。

で、それに加えて青柳さんのとてもわかりやすい説明が!どうもありがとうございます。
ICollection<T>.Add(T) を順番に呼ぶというのが決まりなので
> コレクションのイニシャライザは「Add だよー」という指定
はできない(Add 固定)ということですかね。

勉強になりました。
# 僕のところと違って田中さんのところはこういうのがあるから好きだ

# re: オブジェクトの初期化 2007/06/30 14:37 επιστημη

こーゆー撒き餌にはほいほい引っかかるのねー♪

# re: オブジェクトの初期化 2007/06/30 15:28 επιστημη

ありゃ? トラックバックが飛ばねぇぞ?
http://blogs.wankuma.com/episteme/archive/2007/06/30/83010.aspx

# re: オブジェクトの初期化 2007/06/30 15:47 R・田中一郎

囚人 さん

>試してないですけど
>List<int> age = new List<int>{ Item[0] = 18, Item[1] = 18, Item[2] = 18 };
>はどうかな?

ふっふっふっ、僕も試していないのですが、数時間後には試せる環境が出来上がる予定なのです。

----------------------------------------------------------
片桐 さん

>んー、VBな頭脳の私の感覚としては、NameもAgeもプロパティだけど、Addはメソッドだからだめなんじゃないかと単純に思いました。<単細胞すぎ(笑)

うーん、というかメソッドの場合、何故 Add のみになるのかが不思議なんですよね。

----------------------------------------------------------
まどか さん

>によると、「Add持つものなら」と書かれていますね。

あ、やっぱり・・・
しかし、コレクションだけ特別視したい気持ちはわからなくもないです。

>匿名型は、ComboBoxのDatasourceに対するカスタムメンバクラスの定義が不要になるのかな?

うーん、__Anonymous というクラスを暗に作るということですから、理屈ではできる筈ですよね。
これも、あと数時間後には試せる筈・・・ふっふっふっ。

>#VBも{}がメジャーな記号になるようですね。

えっ、VB でも同じような記法なんですか?!

----------------------------------------------------------
青柳 臣一 さん

>ここに書いてありますが、collection initializer は ICollection<T>.Add(T) を順番に呼び出すだけですね。

あっ、本当ですね。
何となくそうなんだろうなー、とは思っていたんですが・・・orz

>想像以上に泥臭い仕様ですが、汎用的にするにはこのくらいにしないとダメだったんでしょうね。

もう少し、いろいろな使い方ができると楽しいのですが、元々そういう目的のものでもなかったのでしょうから仕方ないですね。
わかりやすいご説明をありがとうございました。

----------------------------------------------------------
επιστημη さん

>ふむ、直接 IEnumerable<T> を引数とするコンストラクタによって初期化しないのはナゼなんだろう。

イニシャライザで{} を用いた場合は、コンストラクタの初期化というのと意味合いが違うということなんでしょうかね。
どちらかというと、コンストラクタを実行するタイミングで外側からメンバに対して何らかの操作を行う際に {} を持ちいるとか。

----------------------------------------------------------
ぽぴ王子 さん

>で、それに加えて青柳さんのとてもわかりやすい説明が!どうもありがとうございます。

僕としては、イニシャライザで、メソッドも自由に呼ばせて欲しかったのですが、それはきっと今回の主目的ではないってことなんでしょうね。
邪魔くさい記述になっちゃいますし。

・・・何かわからないけど、今メッセージが表示されました。
何やら、Orcas のインストールに失敗したらしい orz

# re: オブジェクトの初期化 2007/07/01 1:31 Kazuki

はてなダイアリーからトラックバックに成功したことがない…
コンボボックスへのデータソースとして匿名型使ってみました。
http://d.hatena.ne.jp/okazuki/20070630/1183220966

当然っちゃ当然ですけどすんなり表示されました。
便利ちっく♪

# re: オブジェクトの初期化 2007/07/02 13:57 R・田中一郎

Kazuki さん

>当然っちゃ当然ですけどすんなり表示されました。
>便利ちっく♪

見ました。
便利ですよねー。

タイトル  
名前  
Url
コメント