Getters, сеттеры и лучшие методы работы. Java против С#

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

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

private String name;

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

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

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

Я могу сделать это, как 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 (особенно, если вы читаете "Эффективная Java" ). Так, например, я предпочитаю неизменность (предоставление сеттеров только тогда, когда это необходимо). Мне просто интересно узнать, как эти практики вписываются в различные способы предоставления сеттеров и геттеров в С#; в основном, как мне перевести лучшие практики из мира Java в С#?

ИЗМЕНИТЬ

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

Как насчет нетривиального свойства (т.е. со значительной обработкой и валидацией)? Могу ли я еще разоблачить его через публичное свойство, но с логикой, заключенной в get и set? Зачем мне/нужно делать это с помощью специальных методов setter и getter (с соответствующей логикой обработки и проверки).

Ответ 1

Pre-С# 6

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

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

public string Foo { get; private set; }

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

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

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

С# 6

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

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

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

public double Area => height * width;

Ответ 2

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

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().

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

public string Name { get; set; }

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

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

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

Ответ 7

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

private string name;

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

Ответ 8

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

Ответ 9

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

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}

Ответ 10

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

// 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
}

Желаю вам удачи в С#

Ответ 11

как и большинство ответов здесь, используйте автоматические свойства. Интуитивно понятный, меньше строк кода, и он более чист. Если вы должны сериализовать свой класс, отметьте атрибут class [Serializable]/[DataConract]. И если вы используете [DataContract], отметьте элемент с помощью

[DataMember(Name="aMoreFriendlyName")]
public string Name { get; set; }

Частный или публичный сеттер зависит от ваших предпочтений.

Также обратите внимание, что для автоматических свойств требуются как получатели, так и сеттеры (общедоступные или частные).

/*this is invalid*/
public string Name 
{ 
    get; 
   /* setter omitted to prove the point*/
}

В качестве альтернативы, если вы хотите только получить/установить, создайте поле поддержки самостоятельно