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


154

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

public int Number { get; } = 0

public int Number => 0;

両者に違いがあるかどうか教えてください。彼らはどのように行動しますか?どちらも読み取り専用ですか?

回答:


266

はい、どちらも読み取り専用ですが、違いがあります。最初のものには、コンストラクターが実行される前に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に評価されるため、結果が異なる可能性があります。


23
2番目のバージョンが常に同じ値を返すわけではないことに注意してください。1つの良い例は、戻ってきrandom.NextInt()た場合です。最初のバージョンはそれを一度評価し、常に同じ値を持ちます。2番目は毎回新しい値を返します。

248

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

これは、DateTimeプロパティを使用するとよくわかります。

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

    public DateTime Now => DateTime.Now;
}

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

説明

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


26
これは私が考える最も重要な違いです。
マシュー

14
受け入れられた回答は、コード例の違いを最も正確に定義していますが、これは2つの構造のより有用な違いを説明しています。
カミルドラカリ2017

3
うわー、あなたは有名なジョン・スキート自身よりも多くの投票を得ました。
machine_1 2017

21

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

最初の例

public int Number { get; } = 0

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

2番目の例

public int Number => 0;

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

どちらも読み取り専用です。


5
...しかしJon Skeetが説明するように、最初のものが返す値を変更できます。
Martin Bonnerはモニカの

2
@MartinBonner ...ただし、コンストラクタ内のみ。
Dennis Kuypers 2017

5
または、いつものように、反射を介して(マイナーなピッキング)
Marco Mp
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.