私は次のコードクラスを持っています:
public class Foo
{
public Nested Bar { get; } = new Nested(this);
public class Nested
{
public Nested(Foo foo)
{
foo.DoSomething();
}
}
private void DoSomething()
{
}
}
ただし、次のコンパイルエラーが発生します。
キーワード「this」は現在のコンテキストでは使用できません
Auto-Property Initializerを使用せずに修正し、代わりにコンストラクターに明示的に移動することができます。
public Nested Bar { get; }
public Foo()
{
this.Bar = new Nested(this);
}
なぜそうなのですか? Auto-Property Initializerは実際にILのコンストラクターコードに変換されませんか?
簡単に言うと、初期化子でthis
を使用することはできません。アイデアは、不完全なオブジェクトがエスケープするのを防ぐことです-Nested(this)
はオブジェクトにanythingを実行でき、非常に混乱し、理解しにくいバグにつながります。初期化子はbefore追加したコンストラクターを実行することに注意してください。同じことがフィールド初期化子でも失敗します。まったく同じ方法です。
private Nested _field = new Nested(this);
基本的に、初期化子は単純初期化を実行することを目的としています-98%の問題を修正します。 this
に関連するものはすべてより複雑であり、独自のコンストラクターを作成する必要があります。タイミングの問題については責任を負います:)
なぜそうなのですか? Auto-Property Initializerは実際にILのコンストラクターコードに変換されませんか?
自動的に実装されるプロパティ初期化子のルールは、同じ理由でフィールド初期化子のルールと同じです。プロパティ初期化子は、フィールド初期化子と同じようにbefore基本クラス本体で実行されることに注意してください。したがって、「やや初期化されていない」オブジェクトのコンテキストにいることになります。コンストラクター本体の間よりもそうです。
したがって、プロパティが次のように変換されていることを想像してください。
private readonly Nested bar = new Nested(this); // Invalid
public Nested Bar
{
get { return bar; }
}
要するに、この制限はあなたが自分自身をトラブルに巻き込むのを防ぐことです。プロパティを初期化するときにthis
を参照する必要がある場合は、2番目の例のように、コンストラクターで手動で参照してください。 (私の経験では比較的まれです。)