値型でのコンストラクタ内でのプロパティの初期化
プログラミングC# 第6版 3.4
class CSample { public CSample (int i) { foo = i; } public int foo { get; set; } }
上記クラス定義は極々普通の定義ですが、これを参照型(class)から値型(struct)に変えるとコンパイルエラーが出ます。
$ csc main.cs Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1 for Microsoft (R) .NET Framework version 3.5 Copyright (C) Microsoft Corporation. All rights reserved. main.cs(5,3): error CS0188: すべてのフィールドが割り当てられるまでは、'this' オブジェクトは使用できません。 main.cs(4,9): error CS0843: 自動的に実装されたプロパティ 'CSample.foo' のバッキング フィールドは、コントロールが呼び出し元に返される前に完全に割り当てられている必要があります。コンストラクタ初期化子から既定のコンストラクタを呼び出すことを検討してください。
値型では常にデフォルトコンストラクタ(引数無しのコンストラクタ)が作られて、そこでの初期化が行われるみたいなんですが、独自にコンストラクタ定義した場合、そのデフォルトコンストラクタが呼ばれないので初期化が行われず、プロパティにアクセスすることすらできなくなるみたいです。
これを回避するためには独自に定義したコンストラクタからデフォルトコンストラクタを明示的に呼んでやれば良いとのこと。
class CSample { public CSample (int i) : this() { // デフォルトコンストラクタを呼ぶ foo = i; } public int foo { get; set; } }
ちなみに参照型の場合は、独自のコンストラクタを定義した場合、デフォルトコンストラクタは定義されず、初期化も独自のコンストラクタの方で行われる?みたいなのでエラーにならないみたいです。
ちょっとこの辺は本にはあまり詳しく書いてなかったので若干憶測が入っていますが・・・。