Лучшие методы получения, установки и свойства. Java против C # - PullRequest
88 голосов
/ 09 февраля 2011

Я сейчас учусь на C # и пытаюсь найти лучший способ сделать что-то. Я родом из Java, поэтому я знаком только с лучшими практиками Java; Я новичок в C #!

В Java, если у меня есть частная собственность, я делаю это;

private String name;

public void setName(String name) {
   this.name = name;
}

public String getName() {
   return this.name;
}

В C # я вижу, что есть много способов сделать это.

Я могу сделать это как Java:

private string name;

public void setName(string name) {
   this.name = name;
}

public string getName() {
   return this.name;
}

Или я могу сделать это так:

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

Или:

public string Name { get; set; }

Какой из них мне следует использовать, и какие предостережения или тонкости связаны с каждым подходом? При создании классов я следую общим рекомендациям, которые я знаю по Java (особенно читаю Effective Java). Так, например, я предпочитаю неизменность (предоставляя сеттеры только при необходимости). Мне просто любопытно посмотреть, как эти методы сочетаются с различными способами предоставления сеттеров и геттеров в C #; по сути, как бы я перевел лучшие практики из мира Java в C #?

EDIT

Я публиковал это как комментарий к ответу Джона Скита, но потом он стал длинным:

А как насчет нетривиального свойства (т. Е. Со значительной обработкой и проверкой, возможно)? Могу ли я по-прежнему предоставлять его через открытое свойство, но с логикой, инкапсулированной в get и set? Почему я должен / должен делать это, имея выделенные методы установки и получения (с соответствующей логикой обработки и проверки).

Ответы [ 12 ]

83 голосов
/ 09 февраля 2011

Pre-C # 6

Я бы использовал последний из них для тривиального свойства. Обратите внимание, что я бы назвал это свойство public , поскольку и методы получения, и установки являются открытыми.

Неизменность - это небольшая проблема с автоматически реализуемыми свойствами - вы не можете написать авто-свойство, которое имеет только геттер; ближайший вы можете прийти:

public string Foo { get; private set; }

что не является действительно неизменным ... просто неизменным вне вашего класса. Поэтому вы можете вместо этого использовать real свойство только для чтения:

private readonly string foo;
public string Foo { get { return foo; } }

Вы определенно не хотите писать getName() и setName(). В некоторых случаях имеет смысл писать методы Get / Set, а не использовать свойства, особенно если они могут быть дорогими, и вы хотите подчеркнуть это. Однако вы должны следовать соглашению о именах .NET PascalCase для методов, и вы не хотите, чтобы тривиальное свойство, подобное этому, в любом случае было реализовано обычными методами - здесь свойство гораздо более идиоматично.

C # 6

Ура, у нас наконец есть правильные автоматически реализованные свойства только для чтения:

// This can only be assigned to within the constructor
public string Foo { get; }

Аналогично для свойств, доступных только для чтения, которые делают , чтобы выполнить некоторую работу, вы можете использовать свойства body-member:

public double Area => height * width;
17 голосов
/ 09 февраля 2011

Если вам нужна только переменная для хранения некоторых данных:

public string Name { get; set; }

Хотите, чтобы она отображалась только для чтения?

public string Name { get; private set; }

Или даже лучше ...

private readonly string _name;

...

public string Name { get { return _name; } }

Хотите выполнить некоторую проверку значений перед назначением свойства?

public string Name 
{
   get { return m_name; }
   set
   {
      if (value == null)
         throw new ArgumentNullException("value");

      m_name = value;
   }
}

Как правило, GetXyz () и SetXyz () используются только в определенных случаях, и вам просто нужноиспользовать свой кишечник, когда он чувствует себя хорошо.В целом, я бы сказал, что большинство свойств get / set не содержат много логики и имеют очень мало неожиданных побочных эффектов, если таковые имеются.Если чтение значения свойства требует вызова службы или получения ввода от пользователя для создания запрашиваемого объекта, я бы обернул его в метод и вызвал бы что-то вроде BuildXyz(), а не GetXyz().

12 голосов
/ 09 февраля 2011

Используйте свойства в C #, а не методы get / set.Они там для вашего удобства, и это идиоматично.

Что касается двух ваших примеров на C #, то один просто синтаксический сахар для другого.Используйте свойство auto, если все, что вам нужно, это простая оболочка вокруг переменной экземпляра, используйте полную версию, когда вам нужно добавить логику в метод получения и / или установки.

5 голосов
/ 09 февраля 2011

Сначала позвольте мне попытаться объяснить, что вы написали:

// private member -- not a property
private string name;

/// public method -- not a property
public void setName(string name) {
   this.name = name;
}

/// public method -- not a property
public string getName() {
   return this.name;
}

// yes it is property structure before .Net 3.0
private string name;
public string Name {
   get { return name; }
   set { name = value; }
}

Эта структура также используется в настоящее время, но она наиболее подходит, если вы хотите сделать некоторые дополнительные функциональные возможности, например, когда установлено значение, вы можете проанализировать его, использовать для своей выгоды и сохранить в приватном члене для изменения внутреннего использования.

С .net Framework 3.0

// this style is introduced, which is more common, and suppose to be best
public string Name { get; set; }

//You can more customize it
public string Name
{
    get;
    private set;    // means value could be set internally, and accessed through out
}

Желаю тебе удачи в C #

5 голосов
/ 09 февраля 2011
public string Name { get; set; }

Это просто автоматически реализованное свойство , которое технически совпадает с обычным свойством.При компиляции будет создано вспомогательное поле.

Все свойства в конечном итоге будут преобразованы в функции, поэтому фактическая скомпилированная реализация в конце будет такой же, как вы привыкли в Java.

Использовать auto- реализованные свойства, когда вам не нужно делать какие-то определенные операции с полем поддержки.В противном случае используйте обычное свойство.Используйте функции get и set, если операция имеет побочные эффекты или требует больших вычислительных ресурсов, в противном случае используйте свойства.

5 голосов
/ 09 февраля 2011

В C # предпочитают свойства для выставления приватных полей для получения и / или установки. Форма Thie вы упоминаете это autoproperty, где получить и установить автоматически генерировать скрытое поле поворота подложки для вас.

Я предпочитаю автоматические свойства, когда это возможно, но вы никогда не должны делать пару методов set / get в C #.

4 голосов
/ 09 февраля 2011

В C # предпочтительным способом являются свойства, а не методы getX() и setX().Также обратите внимание, что C # не требует, чтобы свойства имели как get, так и set - вы можете иметь свойства только для get и свойства только для set.

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}
4 голосов
/ 09 февраля 2011

Когда бы ни было возможно, я предпочитаю публичный string Name { get; set; }, поскольку он краткий и легко читаемый.Тем не менее, могут быть случаи, когда это необходимо

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}
4 голосов
/ 09 февраля 2011

Независимо от того, какой путь вы выберете в C #, конечный результат один и тот же.Вы получите переменную backinng с отдельными методами get и setter.Используя свойства, вы следуете передовым методам, поэтому вопрос в том, насколько многословным вы хотите стать.

Лично я бы выбрал авто-свойства, последняя версия: public string Name { get; set; }, так как они занимают меньше всего места.И вы всегда можете расширить их в будущем, если вам нужно добавить что-то вроде валидации.

3 голосов
/ 09 февраля 2011

Как уже упоминалось, все эти подходы приводят к одному и тому же результату. Самое главное, что вы выбираете конвенцию и придерживаетесь ее. Я предпочитаю использовать два последних примера свойств.

...