web-dev-qa-db-ja.com

異なるゲッタースタイル間のC#の違い

ゲッターのプロパティに略語が表示されることがあります。例えば。これら2つのタイプ:

public int Number { get; } = 0

public int Number => 0;

これら2つの間に違いがあるかどうかを教えてください。彼らはどのように振る舞いますか?両方とも読み取り専用ですか?

152
WoIIe

はい、両方とも読み取り専用ですが、違いがあります。最初のものには、コンストラクターが実行される前に0に初期化されるバッキングフィールドがあります。値は、通常の読み取り専用フィールドと同様に、コンストラクターのみで変更できます。ゲッター自体はフィールドの値を返すだけです。

2番目の例では、ゲッターは毎回0を返すだけで、フィールドは関係しません。

そのため、自動的に実装されたプロパティまたは式を使用したメンバーをまったく使用しないようにするために、次のものがあります。

最初のバージョン

private readonly int _number = 0;
public int Number { get { return _number; } }

第2バージョン

public int Number { get { return 0; } }

違いのより明確な例は、次のように表示されます。

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

単一のオブジェクトを作成する場合、そのCreationTimeプロパティは常に同じ結果を返します。これは、オブジェクトの構築時に初期化された読み取り専用フィールドに格納されるためです。ただし、CurrentTimeプロパティにアクセスするたびに、DateTime.UtcNowが評価されるため、結果が異なる可能性があります。

264
Jon Skeet

1つの違いは、0が評価されるとき:オブジェクトの作成時、またはプロパティが使用されるときです。

これは、DateTimeプロパティでよりよく見ることができます。

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

Startプロパティは同じ時刻(インスタンスが作成されたとき)を返し続けますが、Nowは現在の時刻を反映するように変更されます。

説明

最初のバージョン( "Start")は、コンストラクターによって上書きされる可能性のある初期値を提供します。したがって、これは一度だけ評価されます。
2番目のバージョン( "Now")は、このプロパティの "getter"になる式を提供します。したがって、これはプロパティが読み取られるたびに評価されます。コンストラクターが上書きできるバッキングフィールドさえありません。

247
Hans Kesting

これらはC#6言語機能です。

最初の例

public int Number { get; } = 0

最初の例は getter-only auto property です。ゲッター専用自動プロパティのバッキングフィールドは、暗黙的に読み取り専用として宣言されます。

2番目の例

public int Number => 0;

2番目の例は、 プロパティのような関数メンバーの式本体 です。 getキーワードはないことに注意してください。これは、式本体構文の使用によって暗示されます。

両方とも読み取り専用です。

20
Jehof