『究極のC#プログラミング』 Chapter12 var宣言とコレクション初期化子
VBのVariant型の悪夢は、var宣言では問題にならない
・1つの宣言で1つの変数しか宣言できない
・宣言時に初期化しないといけない
・したがって、型はコンパイル時に厳格に決定される(軽量言語にあるような実行時まで型の解釈を遅延する機能とは異なる)
メリット
逆にメリットとして、
・冗長性を排除できる
List<int> list = new List<int>(); //↓ var list = new List<int>();
ただし、
(型名) hoge = (値);
などを
var hoge = (値);
とするのが良いかは微妙。分かりやすさを損なう。
しかし、ややこしい型名を書かずにvarで済ますのが便利なことはある。
var宣言の制限
・型を決めるヒントのない式は代入できない
var a; // エラー
・これと関連して、ラムダ式や匿名メソッドには使えない(型を決めるヒントのない式だから)
var calc = () => 1 + 2; // エラー var calc = delegate() { return 1 + 2; }; // エラー
一応、型の明示したデリゲートであればvar宣言できるが、varを使わない方がカッコ無しで書けるので短く書ける
var calc = (Func<int>)(() => 1 + 2); // ok var calc = Func<int> () => 1 + 2; // カッコ無しはエラー Func<int> calc = () => 1 + 2; // この方が短く書ける
・nullで初期化はできない(型を決めるヒントのない式だから)
ただしキャストすれば初期化できる。
var x = (string)null;
・ローカル変数にしか使えない
class Sample { private var a = 1; // フィールドにvar宣言は使えない }
varの活用例
using文
using(var writer = File.CreateText("log.txt"))
foreach文
foreach(var item in items) // コレクションのアイテムの型はコレクションの型であると決まっているので、明示的に型を指定する意味はない
配列をvar宣言
var array = new int[10]; var array = { 1, 2, 3 }; // error var array = new [] { 1, 2, 3 };
var array = new[] { 1, 1.1, 1.2}; // double型になる
クラスAを継承したクラスB, Cがあった時、
var array = new[] { new A(), new B(), new C() };
の型はAになる。
しかし、
var array = new[] { new B(), new B(), new C() };
はA[]という推測が出来ないので、
A[] array = new[] { new B(), new B(), new C() };
のように型を明示的に指定する必要がある。
var array = new[] { null, null }; // 型を決定できないのでエラー var array = new[] { "A", null }; // これならOK var array = new[] { (string)null, null }; // これもOKだが、普通は次のように書く string array = new[] { null, null }; // これもOK
コレクション初期化子: コレクションのインスタンス生成時に、コレクションの初期値を指定する
var list = new List<int>() { 1, 2, 3 }; // Addメソッドで順次追加するのと同じ
AddメソッドとIEnumerableを実装すれば、自作のコレクション初期化子ができる。
Dictionaryクラスでもコレクション初期化子を利用できる
var t = new Dictionary<int, string>() { {0, "A"}, {1, "B"} };
引数2, 3個のAddメソッドを定義してコレクション初期化子を自作することも可能。