C#6では、ゲッターのみの自動プロパティを使用して、プロパティの実装を簡素化できます。たとえば、抽象Stream
クラスを実装していた場合:
public override bool CanRead { get; } = true;
ただし、C#6の新機能である式の本文を使用して記述することもできます。
public override bool CanRead => true;
2つの違いは何ですか?どちらを使用する必要がありますか?
それらは2つの異なるものの構文糖衣です。前者はバッキングフィールドを初期化し、フィールドの初期化中に割り当ての右側の式に設定します。後者は、式の内容を正確に実行するget
を作成します。
public override bool CanRead { get; } = true;
に相当
private readonly bool __backingFieldCanRead = true;
public override bool CanRead
{
get
{
return __backingFieldCanRead;
}
}
この
public override bool CanRead => true;
に相当
public override bool CanRead
{
get
{
return true;
}
}
それらは異なった振る舞いをします。最初のケースは、オブジェクトが作成されてフィールドが初期化されるときにプロパティの値を設定し、もう1つのケースは、プロパティのゲッターが呼び出されるたびに式を評価します。ブールの単純なケースでは、動作は同じです。ただし、その表現が副作用を引き起こす場合は、状況が異なります。この例を考えてみましょう。
class Program
{
static void Main(string[] args)
{
var fooBar1 = new FooBar();
Console.WriteLine(fooBar1.Baz);
Console.WriteLine(fooBar1.Baz);
var fooBar2 = new FooBar();
Console.WriteLine(fooBar2.Baz);
Console.WriteLine(fooBar2.Baz);
}
}
public class FooBar
{
private static int counter;
public int Baz => counter++;
}
ここでは、「0、1、2、3」が印刷されています。 static counter
フィールドは、プロパティのゲッターが呼び出されるたびに増分されます。ただし、プロパティ初期化子を使用すると、次のようになります。
public int Baz { get; } = counter++;
次に、式がオブジェクトのコンストラクターで評価されるため、「0、0、1、1」が出力されます。
私たちの例で説明する場合、私は以前は次のことを好みました。
public override bool CanRead { get; } = true;
しかし、今日、この実装によってバッキングフィールドにメモリが割り当てられることを通知しました。したがって、この実装:bool CanRead => true;
4バイト節約できます。