Геттеры, сеттеры и свойства рекомендации. Ява и C#


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

EDIT

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

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

11 85

11 ответов:

Pre-C# 6

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

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

public string Foo { get; private set; }

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

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

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

public double Area => height * width;

если все, что вам нужно-это переменная для хранения данных:

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

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

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

в C# favor свойства для предоставления частных полей для get и / или set. Форма thie, которую вы упоминаете, является автопропертией, где get и set автоматически генерируют скрытое поле поддержки pivot для вас.

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

public string Name { get; set; }

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

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

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

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

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

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

private string name;

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

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

public boolean MyProperty
{
    get { return something; }
}

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

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

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

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

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

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

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

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

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

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