Автоматичні властивості C # 3.0 - корисні чи ні? [зачинено]


155

Примітка. Це було опубліковано, коли я починав C #. Маючи знання про 2014 рік, я можу по-справжньому сказати, що автоматичні властивості є одними з найкращих речей, які коли-небудь траплялися з мовою C #.

Мене використовують для створення своїх властивостей у C # за допомогою приватного та загальнодоступного поля:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Тепер із .NET 3.0 ми отримали автоматичні властивості:

public string Title { get; set; }

Я знаю, що це скоріше філософські / суб'єктивні питання, але чи є причина використовувати ці автовластивості, крім збереження п'яти рядків коду для кожного поля? Моя особиста прихильність полягає в тому, що ці властивості приховують від мене речі, і я не є великим прихильником чорної магії.

Насправді приховане приватне поле навіть не відображається у відладчику, що добре, враховуючи той факт, що функції get / set функції нічого не роблять. Але коли я хочу реально реалізувати певну логіку геттера / сетера, я все одно повинен використовувати приватну / публічну пару.

Я бачу вигоду в тому, що я зберігаю багато коду (один проти шести рядків), не втрачаючи можливості змінити логіку геттера / сеттера пізніше, але потім знову вже можу це зробити, просто оголосивши публічне поле "Публічний заголовок рядка" без потреба {get; набір; } блок, таким чином навіть економлячи більше коду.

Отже, чого я тут пропускаю? Чому хтось насправді хотів би використовувати авто-властивості?


86
"Моя особиста захоплення полягає в тому, що ці властивості приховують від мене речі, і я не є великим шанувальником чорної магії". Так? Ви знаєте, що компілятор весь час приховує від вас тонну, правда? Якщо ви не пишете збірку (або точніше, фактичні позначки 1 і 0 для вашого коду), ВСЕ, що ви пишете, приховує від вас речі.
Charles Boyung

Відповіді:



62

Так, це просто зберігає код. Милі легше читати, коли ти навантажуєш їх. Вони швидше писати і простіші в обслуговуванні. Збереження коду - це завжди хороша мета.

Ви можете встановити різні сфери застосування:

public string PropertyName { get; private set; }

Так що властивість можна змінити лише всередині класу. Це насправді незмінне, оскільки ви все одно можете отримати доступ до приватного сетера через роздуми.

На C # 6 ви також можете створити справжні readonlyвластивості - тобто незмінні властивості, які не можна змінити поза конструктором:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

Під час компіляції, який стане:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

У незмінних класах з великою кількістю членів це економить багато зайвого коду.


"Таким чином, ви не втрачаєте жодної функціональності." як ви їх налагоджуєте?
wal

2
@wal - що тут налагодити? З цієї точки зору ви в основному маєте справу зі змінними-членами.
Кіт

6
@wal - Ви можете поставити на них точку перелому, як і ви можете отримати доступ до змінної члена, ви просто не можете вступити в них. Але чому б ти цього хотів? Автоматичні властивості насправді є тривіальними та автоматично генерованими, якщо у вас є помилки, це одне місце, яке вони вкрай малоймовірні.
Кіт

3
нам може знадобитися взяти це за межами Кіта. :)
wal

1
Але гаразд, припустимо, у вас є багато викликів у програмі myObj.Title ... ви хочете побачити, де значення змінюється з "тексту" на "null", тобто умовної точки перерви. як ти можеш це зробити? Ви навіть не можете встановити точку розриву на сетері
пройдіть

45

Три великих недоліки використання полів замість властивостей:

  1. Ви не можете прив’язати дані до поля, тоді як ви можете до власності
  2. Якщо ви почнете використовувати поле, ви не зможете пізніше (легко) змінити їх у властивість
  3. Є деякі атрибути, які ви можете додати до властивості, яку ви не можете додати до поля

7
"Якщо ви почнете використовувати поле, ви не зможете пізніше (легко) змінити їх на властивість", вибачте, але чому?
Хомам

6
@Homam Головним чином, будь-який споживчий код, який використовує відображення у ваших полях, порушиться, оскільки їм доведеться перейти з використання FieldInfo на PropertyInfo.
WCWedin

8
@Homam Крім того, зміна поля на властивість порушує двійкову сумісність, вимагаючи від всіх споживачів поля перекомпілювати.
Одраде

1
Проблеми з перекомпіляцією та відображенням убік, дуже просто інкапсулювати поля за допомогою Visual Studio: Ctrl-R + E дозволить перетворити поле у ​​властивість за допомогою відповідних геттерів / сетерів. (або клацніть правою кнопкою миші поле, рефактор, поле інкапсуляції).
JoeBrockhaus

Поля @Hommam - це значення (вони є змінними), а властивості - ні. Речі, які могли скласти, коли це було поле, можуть бути не, коли це властивість.
Марк

29

Я особисто люблю авто-властивості. Що не так із збереженням рядків коду? Якщо ви хочете робити речі в геттерах або сетерах, згодом не виникає проблем перетворити їх у звичайні властивості.

Як ви сказали, ви можете використовувати поля, і якщо ви хочете пізніше додати логіку до них, перетворите їх у властивості. Але це може створити проблеми при використанні рефлексії (а можливо, і в іншому місці?).

Також властивості дозволяють встановлювати різні рівні доступу для геттера та сеттера, які ви не можете зробити з полем.

Я думаю, це те саме, що і ключове слово var. Справа в особистих уподобаннях.


29

Від Bjarne Stroustrup, творець C ++:

Мені особливо не подобаються заняття з великою кількістю функцій отримання та встановлення. Це часто свідчить про те, що це не повинно було бути в першу чергу класом. Це просто структура даних. І якщо це справді структура даних, зробіть це структурою даних.

А ви знаєте що? Він правий. Як часто ви просто загортаєте приватні поля в get і set, не роблячи насправді нічого в межах get / set, просто тому, що це "об'єктно-орієнтована" річ. Це вирішення проблеми Microsoft; вони в основному є загальнодоступними полями, до яких можна зв’язатись.


2
Я дійсно думаю, що це повинно мати більше балів. Занадто багато людей бачать автоматичні властивості як зелене світло для написання жахливо інкапсульованих (або зовсім не інкапсульованих) класів, що є трохи більше, ніж прославлене публічне поле. Звичайно, це більше питання про те, як люди використовують інструмент, а не сам інструмент, але я думаю, що це важливо згадати, обговорюючи властивості в цілому.
сара

18

Одне, що, здається, ніхто не згадував - це те, як, наприклад, автоматичні властивості не корисні для незмінних об'єктів (як правило, незмінних структур). Тому що для цього вам справді слід зробити:

private readonly string title;
public string Title
{
    get { return this.title; }
}

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

Таким чином, це має переваги перед простим get/ private setавтовластивістю.


Якщо у вас є структура, яка змінює будь-яке властивість, це призводить до появи нової структури. Це може бути проблемою лише в тому випадку, якщо ви хочете внутрішньо непорушного типу довідки - я не бачу причини, чому вам коли-небудь знадобиться.
Кіт

@Keith: Ваше перше речення здається фактично неправильним.
Доменіч

3
Не став би public string Title { get; private set; }результат таким же чином? Ви могли б змінити його зсередини класу, але, звичайно, але якщо у вас виникнуть інші проблеми ...: p
Свиш

2
@Svish - за цим аргументом ключове слово readonly у C # ніколи не повинно використовуватися, оскільки його використання означатиме, що ми приховували ці "різні проблеми"
Заїд Масуд,

2
Я маю на увазі, що з точки зору зовнішнього API це не має великого значення. Отже, автоматичні властивості можна використовувати за бажанням. Найкраще, звичайно, було б, якби ти міг зробити щось на кшталтpublic string Title { get; private readonly set; }
Свиш

12

Я завжди створюю властивості замість загальнодоступних полів, оскільки ви можете використовувати властивості у визначенні інтерфейсу, ви не можете використовувати загальнодоступні поля у визначенні інтерфейсу.


8

Авто-властивості - це настільки ж чорна магія, як і все, що в C #. Коли ви думаєте про це з точки зору складання до IL, а не для розширення до звичайного властивості C #, спочатку це набагато менше чорної магії, ніж безліч інших мовних конструкцій.


5

Я постійно використовую автоматичні властивості. Перед C # 3 я не міг заважати всім набравши текст, а натомість просто використовував загальнодоступні змінні.

Єдине, що мені не вистачає, це зробити це:

public string Name = "DefaultName";

Вам потрібно перенести за замовчуванням у ваші конструктори з властивостями. нудно :-(


4
З ініціалізаторами автоматичної власності від C # 6 ви незабаром зможете це зробити: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Карлос

5

Я думаю, що будь-яка конструкція, інтуїтивно зрозуміла І зменшує рядки коду, є великим плюсом.

Ці види функцій - це те, що робить мови, такі як Ruby, настільки потужними (що і динамічні функції, які також допомагають зменшити зайвий код).

У Рубі все це було так:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

Єдина проблема, з якою у мене є, - це те, що вони не йдуть досить далеко. Той самий випуск компілятора, який додав автоматичні властивості, додав часткові методи. Чому вони не склали двох разом, це поза мною. Просте "часткове ввімкнення <PropertyName> Changed" зробило б ці речі справді корисними.


Можна помістити кілька часткових методів всередину іншого методу. Створення якогось автоматичного шаблону для них було б заплутаним.
Матвій Віт

2

Це просто, він короткий, і якщо ви хочете створити реальну реалізацію всередині тіла властивості десь внизу лінії, це не порушить зовнішній інтерфейс вашого типу.

Так просто.


1

Тут слід зазначити одне, що, наскільки я розумію, це просто синтаксичний цукор на кінці C # 3.0, що означає, що IL, створений компілятором, є однаковим. Я згоден про те, щоб уникнути чорної магії, але все-таки менше рядків для однієї і тієї самої речі - це зазвичай добре.


1

На мою думку, ви завжди повинні використовувати автоматичні властивості замість публічних полів. Однак це є компроміс:

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

  • потрібен доступ до поля поза його складанням, або
  • потрібно приєднати логіку до геттера / сеттера

Зробити це:

  1. перейменуйте поле
  2. зробити його приватним
  3. додати суспільну власність

Ваш клієнтський код не потрібно буде змінювати.

Однак колись ваша система буде рости, і ви розкладете її на окремі збірки та декілька рішень. Коли це станеться, будь-які відкриті поля повернуться до переслідування, тому що, як зазначав Джефф, зміна публічного поля на публічну власність - це переломна зміна API .


0

Я використовую CodeRush, це швидше, ніж автоматичні властивості.

Зробити це:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Потрібно вісім натискань клавіш.


5
Якщо я утримую CTRL і V, я можу вставити багато і багато речей, / дуже швидко /, але це не робить його "кращим". Як це відповідає на початкове запитання?
JBRWilkinson

0

Ну а з фрагментами коду автоматеріал з однойменною назвою складатиме сім клавіш;)


0

@Domenic: Я цього не розумію .. хіба ти не можеш це зробити з автоматичними властивостями ?:

public string Title { get; }

або

public string Title { get; private set; }

Це те, про що ти маєш на увазі?


Ви можете (останнє; перше не збиратиметься), але тоді поле не є непорушним всередині вашого об'єкта.
Доменіч

Слова застереження, лише структури незмінні, коли вони позначені повторно, класи просто неможливі.
Гуванте

0

Моя найбільша боротьба з автоматичними властивостями полягає в тому, що вони створені, щоб заощадити час, але я часто виявляю, що мені доведеться пізніше розширити їх на повноцінні властивості.

Те, що VS2008 не вистачає, - це " Властивий автоматеріал" рефактор .

Той факт, що ми маємо інкапсульований рефактор поля, робить роботу, яку я швидше працюю, просто використовувати загальнодоступні поля.

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