2016-10-19 10 views
3

自動プロパティに設定されたデフォルト値を取得して、FodyでILを作成したいとします。自動プロパティの初期化IL命令の命令

私が理解しているように、初期化はコンストラクタのバッキングフィールドを設定する単なる構文糖です。だから私は、現在のプロパティのバッキングフィールドを設定するstfld命令への最後のプロパティの初期化の最後からの命令でデフォルト値が作成されたと考えました。

ただし、これはコンストラクタの最初のものとして常に初期化が行われることを前提としています。それは正しい仮定ですか?最適化などの考慮すべきエッジケースはありますか?

+0

私はすでにそれを行っているC#でいくつかのサンプルを書くと、生成されたIL –

+1

をご確認ください。それは私が言及した前提につながります。私は例外がないことを確かめたい。 –

答えて

4

私はここではC#6

のための新しい言語機能を記述するC#のに今後の特長と題したこのpdfファイルは自動プロパティの初期化子に関するセクションが(強調は私です)ですが見つかりました:

イニシャライザはバッキングフィールドを直接初期化します。それは自動作成の設定者を通しては機能しません。

イニシャライザは、フィールドイニシャライザと同様に、書かれているように、順番に実行されます。

フィールド初期化子のように、自動プロパティ初期化子は、オブジェクトが正しく初期化される前に、すべてが実行された後に 'this'を参照することはできません。これは、自動プロパティを初期化するための興味深いものがたくさんあるということを意味します。しかし、主なコンストラクタはそれを変更します。オートプロパー 初期化子と一次コンストラクタは、お互いを強化します。

フィールド初期化子と自動プロパティ初期化子は等しく扱われるので、C#仕様の次のセクションもautoプロパティの初期化に適用する必要があります。

10.11.3コンストラクタ実行

変数イニシャライザは代入文に変換され、これらの代入文は、基本クラスのインスタンスコンストラクタを呼び出す前に実行されます。この順序付けにより、すべてのインスタンスフィールドが変数イニシャライザによって初期化され、そのインスタンスにアクセスできるステートメントが実行されます。

...

自動的にコンストラクタ-体の前に挿入されている文としてインスタンス変数の初期化子とコンストラクタ初期化子を考えると便利です。

+0

リンクがあなたのハードドライブにリンクしようとしているようです。 – svick

+0

申し訳ありません。私はそれを修正します。 –

+0

あなたはエッジケースについて尋ねましたが、質問に答えるのを忘れましたか? –

1

まず、一般的な注記:ILを分析して得られるように、「価値」について語ります。 thisが含まれていない限り、表現は何でもよいので、これは一般的ではありません。値を計算する命令だけが得られますが、これはアプリケーションにとっては十分かもしれません。これの意味論は予測が、明らかではありません

public int i { get; set; } = s = t = 1; 
public static int s { get; set; } = t; 
public static int t = 2; 

sのデフォルト値は0であるエッジケースでは、特に、式はプロパティのバッキングフィールド以外のフィールドを初期化する可能性があるという事実を考えます(初期化が宣言順序で起こるためtが明示的にこの時点で初期化されていない)、tのデフォルト値は2であり、そしてiのデフォルト値は、それが発生した場合、その初期化は、また、tとを設定ひねりと、1その後、s 1に、この場合のILコードから値を導出することは容易ではありません、とさえ初期化子を識別することは、あなたが考えることを必要とするを/stsfld命令は、古いフィールドとは対照的に、プロパティのバッキングフィールドに割り当てます。

簡単に言えば、プロパティが型のデフォルト値に初期化されている場合、コンパイラはnewobjによって処理されるため、プロパティの初期化を完全に省略することがあります。 ILレベルでは、次のように同じコードをもたらし得る:

int a { get; set; } = 3/4; 

int a { get; set; } 

これはコードで初期化どのように見えるかに存在しなくてもよいという意味でのエッジケースでありますILはまったくありません。あなたが興味を持っているのは、明示的なイニシャライザが使われたかどうかではなく、値であるならば、もちろん問題ありません。

+0

バッキングフィールドを設定する最初の 'stsfld'または' stfld'コールの直前で値を取得するだけでは不十分でしょうか。それはセマンティクスの複雑さにかかわらず、デフォルト値を与えるはずです。ところで、あなたが言及した最後のものを見たことがありますが、実際には結果が変わらないので無視しました。 –

+0

@ qqww2:実行時にのみ値が必要な場合は、実際に設定されているコンストラクタ内のポイントに指示を挿入できます。プログラマがイニシャライザを使用せず、コンストラクタにプロパティを設定するだけで(setterを呼び出す)、ケースを処理するかどうかを検討する必要があります。バッキングフィールドの初期化と同じではありませんが、クラスのクライアントと同じセマンティクスを持ちます。 –

+0

実際、私はコンストラクタで設定された値には興味がありません。 –