Різниця в C # між різними стилями геттера


154

Я інколи бачу абревіатури у властивостях для геттера. Наприклад, ці два типи:

public int Number { get; } = 0

public int Number => 0;

Чи можете мені хтось сказати, чи є різниці між цими двома. Як вони поводяться? Вони обидва лише для читання?

Відповіді:


266

Так, обидва вони лише для читання, але є різниця. У першому є поле резервного копіювання, яке ініціалізується до 0 перед виконанням конструктора. Ви можете змінити значення лише в конструкторі , як і звичайне поле лише для читання. Сам гетьтер просто повертає значення поля.

У другому - геттер щоразу повертає 0, без поля.

Таким чином, щоб взагалі не використовувати будь-які автоматично реалізовані властивості або виражені членами, ми маємо:

Перша версія

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

Друга версія

public int Number { get { return 0; } }

Більш чіткий приклад різниці може бути таким:

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

Якщо ви створюєте один об'єкт, його CreationTimeвластивість завжди буде давати однаковий результат - оскільки він зберігається в полі для читання, ініціалізованому на побудові об'єкта. Однак кожен раз, коли ви звертаєтесь до CurrentTimeресурсу, це спричинить DateTime.UtcNowоцінку, ви отримаєте потенційно інший результат.


23
Зверніть увагу, що друга версія не завжди повертає однакове значення. Хороший приклад - якщо ви повернетесь random.NextInt(). Перша версія оцінить, що колись і завжди мають однакове значення. Другий щоразу повертає нове значення.

248

Одна різниця полягає в тому, коли 0це оцінюється: при створенні об'єкта або коли використовується властивість.

Це ви можете побачити краще за властивостями DateTime:

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

    public DateTime Now => DateTime.Now;
}

StartВластивість постійно повертається в той же час (в момент створення екземпляра), в той час як Nowзміни , щоб відобразити поточний час.

Пояснення :

Перша версія ("Пуск") надає початкове значення, яке може бути навіть перезаписане конструктором. Тож це оцінюється лише один раз.
Друга версія ("Тепер") надає вираз, який буде "getter" цієї властивості. Отже, це оцінюється щоразу, коли властивість читається. Не існує навіть резервного поля, яке конструктор може перезаписати.


26
Це найважливіша відмінність, на мою думку.
Матвій

14
Прийнята відповідь найбільш точно визначає різницю в прикладі коду, але це пояснює більш корисну різницю в двох структурах.
Каміль Дракарі

3
Нічого собі, ви отримали більше голосів, ніж сам знаменитий Джон Скіт.
машина_1

21

Це мовні особливості C # 6.

Перший приклад

public int Number { get; } = 0

Перший приклад - це власність, призначена лише для отримання геттера . Поле резервного копіювання автоматеріалу лише для отримання, неявно оголошується як прочитане.

Другий приклад

public int Number => 0;

А другий приклад - це тіла виразів на власних функціональних елементах . Зауважте, що не існує жодного getключового слова: мається на увазі через використання синтаксису тіла вираження.

Обидва читаються тільки.


5
... але, як пояснює Джон Скіт, ви можете змінити значення, яке повертається першим.
Мартін Боннер підтримує Моніку

2
@MartinBonner ... але тільки в конструкторі.
Dennis Kuypers

5
або, як завжди, через рефлексію (незначне занизування)
Marco Mp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.