Подтвердить что ты не робот

В чем разница между свойствами автогенератора и свойствами тела выражения?

В С# 6 вы можете упростить реализацию свойства, используя свойство auto-only auto. Например, если бы я реализовал абстрактный Stream класс:

public override bool CanRead { get; } = true;

Однако я также могу написать его с телом выражения, также новым в С# 6:

public override bool CanRead => true;

В чем разница между ними и когда я должен использовать один или другой?

4b9b3361

Ответ 1

Это синтаксический сахар для двух разных вещей. Бывший инициализирует поле подложки, и устанавливает его в выражение на правой стороне задания во время инициализации поля. Последний создает 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;
    }
}

Они ведут себя по-разному. Первый случай устанавливает значение свойства при создании объекта и инициализации поля, а другой случай оценивает выражение каждый раз, когда вызывается свойство getter. В простом случае bool поведение одинаково. Однако, если выражение вызывает побочные эффекты, все по-другому. Рассмотрим этот пример:

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". Статическое поле counter увеличивается каждый раз, когда вызывается свойство getter. Однако с инициализатором свойств:

public int Baz { get; } = counter++;

Затем выводится "0, 0, 1, 1", потому что выражение оценивается в конструкторе объекта.

Ответ 2

В случае, который вы описываете в нашем примере, я предпочитал:

public override bool CanRead { get; } = true;

Но сегодня я уведомил, что эта реализация вызывает выделение памяти для вспомогательного поля. И так, эта реализация: bool CanRead => true; может сохранить 4 байта.