Геттеры, сеттеры и свойства рекомендации. Ява и 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 ответов:
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*/ }
кроме того, если вы только хотите получить / установить, создайте резервное поле самостоятельно