Что в C # отличает поле от свойства и когда следует использовать поле вместо свойства?
Что в C # отличает поле от свойства и когда следует использовать поле вместо свойства?
Ответы:
Свойства выставляют поля. Поля должны (почти всегда) быть приватными для класса и доступны через свойства get и set. Свойства обеспечивают уровень абстракции, позволяющий вам изменять поля, не влияя на внешний доступ к ним со стороны вещей, которые используют ваш класс.
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
@Kent указывает, что свойства не требуются для инкапсуляции полей, они могут выполнять вычисления в других полях или служить другим целям.
@GSS указывает, что вы также можете использовать другую логику, например, проверку доступа к свойству, еще одну полезную функцию.
string
, мой контракт: назначить любые символы до ~ 2bil длины. Если свойство есть DateTime
, мой контракт: назначить любые числа в пределах DateTime, которые я могу посмотреть. Если создатель добавляет ограничения в установщики, эти ограничения не передаются. Но если вместо этого создатель изменяет тип с string
на Surname
, то его новый класс Фамилия сообщает об ограничениях, и свойство public Surname LastName
не имеет проверки установщика. Кроме того, Surname
является многоразовым.
Surname
в моем примере это можно многократно использовать, вам не нужно беспокоиться о дальнейшем копировании / вставке этих проверок в установщике свойств в другие места кода. Не удивительно, если проверка Фамилии происходит в нескольких местах, если вы когда-либо вносите изменения в бизнес-правила для Фамилий. Проверьте ссылку, которую я отправил о Value Objects
Принципы объектно-ориентированного программирования говорят о том, что внутренняя работа класса должна быть скрыта от внешнего мира. Если вы выставляете поле, вы, по сути, выставляете внутреннюю реализацию класса. Поэтому мы заключаем поля в свойства (или методы в случае Java), чтобы дать нам возможность изменить реализацию, не нарушая код в зависимости от нас. То, как мы можем поместить логику в Свойство, также позволяет нам выполнять логику проверки и т. Д., Если нам это нужно. C # 3 имеет, возможно, запутывающее представление об авто свойствах. Это позволяет нам просто определить свойство, и компилятор C # 3 сгенерирует для нас приватное поле.
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
public int myVar { get; set; }
самом деле означает (и я предполагаю, что это причина как минимум 50% показов получает этот вопрос).
virtual
сами являются частью объектно-ориентированного программирования.
virtual
ООП как таковой. Это инструмент, который обеспечивает полиморфизм, который является одним из ключевых инструментов, который включает ООП. Это не ООП само по себе, хотя, и нет ничего по сути ООП в отношении публичного автоприменения. Я бы не стал считать такие вещи, как рефлексия или привязка к ООП, связанные с данными. Обычно я не был бы настолько педантичен в этом, но в ответе конкретно упоминались ОО-принципы как движущая сила примера кода, и я не согласен с этим.
Важным отличием является то, что интерфейсы могут иметь свойства, но не поля. Для меня это подчеркивает, что свойства должны использоваться для определения открытого интерфейса класса, в то время как поля предназначены для использования в частной, внутренней работе класса. Как правило, я редко создаю открытые поля и так же редко создаю непубличные свойства.
Я дам вам несколько примеров использования свойств, которые могут привести к вращению шестерен:
Используя Свойства, вы можете вызвать событие, когда значение свойства изменяется (aka. PropertyChangedEvent) или перед изменением значения для поддержки отмены.
Это невозможно с полями (прямой доступ).
public class Person {
private string _name;
public event EventHandler NameChanging;
public event EventHandler NameChanged;
public string Name{
get
{
return _name;
}
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
private void OnNameChanging(){
NameChanging?.Invoke(this,EventArgs.Empty);
}
private void OnNameChanged(){
NameChanged?.Invoke(this,EventArgs.Empty);
}
}
Поскольку многие из них объяснили с техническими плюсами и минусами Properties
и Field
, пришло время перейти к примерам в реальном времени.
1. Свойства позволяют установить уровень доступа только для чтения.
Рассмотрим случай dataTable.Rows.Count
и dataTable.Columns[i].Caption
. Они приходят из класса, DataTable
и оба являются для нас публичными. Разница в уровне доступа к ним заключается в том, что мы не можем установить значение, dataTable.Rows.Count
но мы можем читать и писать dataTable.Columns[i].Caption
. Это возможно через Field
? Нет !!! Это может быть сделано Properties
только с.
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
2. Свойства в PropertyGrid
Возможно, вы работали Button
в Visual Studio. Его свойства отображаются в том же PropertyGrid
духе Text
и Name
т. Д. Когда мы перетаскиваем кнопку и когда щелкаем свойства, она автоматически находит класс Button
и фильтры Properties
и показывает их в PropertyGrid
(где PropertyGrid
не будет отображаться, Field
даже если они общедоступны).
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
В PropertyGrid
свойствах Name
и Text
будет показано, но нет SomeProperty
. Почему??? Потому что свойства могут принимать атрибуты . Это не показывает в случае, когда [Browsable(false)]
ложно.
3. Может выполнять операторы внутри свойств
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
4. В Binding Source можно использовать только свойства
Binding Source помогает нам уменьшить количество строк кода. Fields
не принимаются BindingSource
. Мы должны использовать Properties
для этого.
5. Режим отладки
Представьте, что мы используем Field
для хранения значения. В какой-то момент нам нужно отладить и проверить, где значение становится нулевым для этого поля. Это будет трудно сделать, когда количество строк кода больше 1000. В таких ситуациях мы можем использовать Property
и можем установить режим отладки внутри Property
.
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
Поле является переменной , которая объявляется непосредственно в классе или структуры. Класс или структура могут иметь поля экземпляра или статические поля или оба. Как правило, вы должны использовать поля только для переменных, которые имеют частную или защищенную доступность . Данные, которые ваш класс предоставляет клиентскому коду, должны предоставляться через методы, свойства и индексаторы. Используя эти конструкции для косвенного доступа к внутренним полям, вы можете защититься от недопустимых входных значений.
Свойство является элементом , который обеспечивает гибкий механизм для чтения, записи или вычислений значения частной области. Свойства можно использовать так, как будто они являются открытыми членами данных, но на самом деле это специальные методы, называемые методами доступа . Это позволяет легко получать доступ к данным, а также способствует безопасности и гибкости методов . Свойства позволяют классу предоставлять открытый способ получения и установки значений, скрывая при этом код реализации или проверки. Метод доступа к свойству get используется для возврата значения свойства, а метод доступа к set используется для назначения нового значения.
Свойства имеют основное преимущество, позволяя вам изменять способ доступа к данным объекта, не нарушая его общедоступный интерфейс. Например, если вам нужно добавить дополнительную проверку или преобразовать сохраненное поле в вычисляемое, вы можете сделать это легко, если вы изначально выставили поле как свойство. Если вы только что выставили поле напрямую, вам придется изменить открытый интерфейс вашего класса, чтобы добавить новые функциональные возможности. Это изменение нарушит работу существующих клиентов и потребует их перекомпиляции, прежде чем они смогут использовать новую версию вашего кода.
Если вы пишете библиотеку классов, предназначенную для широкого потребления (например, .NET Framework, которой пользуются миллионы людей), это может стать проблемой. Однако, если вы пишете класс, используемый внутри небольшой базы кода (скажем, <= 50 тыс. Строк), это на самом деле не имеет большого значения, потому что ваши изменения ни на кого не повлияют. В этом случае все сводится к личным предпочтениям.
Свойства поддерживают асимметричный доступ, т. Е. Вы можете иметь либо геттер и сеттер, либо только один из двух. Точно так же свойства поддерживают индивидуальную доступность для getter / setter. Поля всегда симметричны, то есть вы всегда можете получить и установить значение. Исключением являются поля только для чтения, которые, очевидно, не могут быть установлены после инициализации.
Свойства могут работать очень долго, иметь побочные эффекты и даже создавать исключения. Поля быстрые, без побочных эффектов и никогда не будут генерировать исключения. Из-за побочных эффектов свойство может возвращать различное значение для каждого вызова (как может иметь место в случае DateTime.Now, то есть DateTime.Now не всегда равен DateTime.Now). Поля всегда возвращают одно и то же значение.
Поля могут использоваться для параметров out / ref, свойства - нет. Свойства поддерживают дополнительную логику - это может быть использовано для реализации отложенной загрузки среди прочего.
Свойства поддерживают уровень абстракции, инкапсулируя все, что это означает, чтобы получить / установить значение.
Используйте свойства в большинстве случаев, но старайтесь избегать побочных эффектов.
В фоновом режиме свойство компилируется в методы. Таким образом, Name
свойство компилируется в get_Name()
и set_Name(string value)
. Вы можете увидеть это, если изучите скомпилированный код. Таким образом, при их использовании возникают (очень) небольшие потери производительности. Обычно вы всегда будете использовать свойство, если вы выставляете поле снаружи, и вы часто будете использовать его внутри, если вам нужно проверить значение.
Если вы хотите, чтобы ваша личная переменная (поле) была доступна для объекта вашего класса из других классов, вам нужно создать свойства для этих переменных.
например, если у меня есть переменные с именами «id» и «name», которые являются частными, но может быть ситуация, когда эта переменная необходима для операции чтения / записи вне класса. В этой ситуации свойство может помочь мне получить эту переменную для чтения / записи в зависимости от получения / набора, определенного для свойства. Свойство может быть доступно только для чтения / записи только / чтения.
вот демо
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
Второй вопрос здесь, «когда следует использовать поле вместо свойства?», Только вкратце затронут в этом другом ответе и вроде как на этом , но не очень подробно.
В общем, все остальные ответы на тему хорошего дизайна: предпочитайте выставлять свойства, а не выставлять поля. Хотя вы, вероятно, не будете регулярно говорить: «Ух ты, представь, насколько хуже будет, если бы я сделал это полем вместо свойства», гораздо реже можно подумать о ситуации, когда ты скажешь «Ух ты, слава богу, я использовал здесь поле вместо собственности ".
Но есть одно преимущество, которое поля имеют над свойствами, и это их способность использоваться в качестве параметров «ref» / «out». Предположим, у вас есть метод со следующей подписью:
public void TransformPoint(ref double x, ref double y);
и предположим, что вы хотите использовать этот метод для преобразования массива, созданного следующим образом:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Вот я думаю, что самый быстрый способ сделать это, так как X и Y являются свойствами:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
И это будет очень хорошо! Если у вас нет измерений, которые доказывают обратное, нет никаких причин вонять. Но я полагаю, что технически не гарантировано, что это будет так быстро:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Выполняя некоторые измерения самостоятельно, версия с полями занимает около 61% времени как версия со свойствами (.NET 4.6, Windows 7, x64, режим выпуска, без отладчика). Чем дороже TransformPoint
становится метод, тем меньше становится разница. Чтобы повторить это самостоятельно, бегите с закомментированной первой строкой и без закомментированной.
Даже если для вышеописанного не было выигрыша в производительности, существуют другие места, где возможность использования параметров ref и out может быть полезной, например, при вызове семейства методов Interlocked или Volatile . Примечание. В случае, если это новость для вас, Volatile - это, по сути, способ добиться того же поведения, которое обеспечивает volatile
ключевое слово. Таким образом, volatile
он не может волшебным образом решить все проблемы с безопасностью потоков, как его название предполагает, что может.
Я определенно не хочу показаться, что я выступаю за то, чтобы вы говорили: «О, я должен начать выставлять поля вместо свойств». Дело в том, что если вам нужно регулярно использовать эти члены в вызовах, которые принимают параметры «ref» или «out», особенно для чего-то, что может быть простым типом значения, которому вряд ли когда-либо понадобится какой-либо из элементов свойств с добавленной стоимостью, аргумент может быть сделан.
Хотя поля и свойства похожи друг на друга, они представляют собой 2 совершенно разных языковых элемента.
Поля являются единственным механизмом хранения данных на уровне класса. Поля являются концептуально переменными в области видимости класса. Если вы хотите сохранить некоторые данные в экземплярах ваших классов (объектов), вам нужно использовать поля. Другого выбора нет. Свойства не могут хранить какие-либо данные, хотя может показаться, что они могут это сделать. Смотрите ниже.
Свойства с другой стороны никогда не хранят данные. Это просто пары методов (get и set), которые можно синтаксически вызывать аналогично полям, и в большинстве случаев они обращаются к (для чтения или записи) полям, что является источником некоторой путаницы. Но поскольку методы свойств являются (с некоторыми ограничениями, такими как фиксированный прототип) обычными методами C #, они могут делать то же, что и обычные методы. Это означает, что они могут иметь 1000 строк кода, они могут генерировать исключения, вызывать другие методы, могут быть даже виртуальными, абстрактными или переопределенными. Особенность свойств заключается в том, что компилятор C # сохраняет некоторые дополнительные метаданные в сборках, которые можно использовать для поиска определенных свойств - широко используемой функции.
Методы получения и установки свойств имеют следующие прототипы.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
Таким образом, это означает, что свойства можно «эмулировать», определив поле и 2 соответствующих метода.
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
Такая эмуляция свойств типична для языков программирования, которые не поддерживают свойства - например, стандартный C ++. В C # там вы всегда должны предпочитать свойства как способ доступа к вашим полям.
Поскольку только поля могут хранить данные, это означает, что чем больше полей содержит класс, тем больше объектов памяти такого класса будет использовать. С другой стороны, добавление новых свойств в класс не делает объекты такого класса больше. Вот пример.
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
Хотя методы свойств могут делать что угодно, в большинстве случаев они служат способом доступа к полям объектов. Если вы хотите сделать поле доступным для других классов, вы можете сделать это двумя способами.
Вот класс с использованием открытых полей.
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
Хотя код является абсолютно корректным, с точки зрения дизайна, он имеет несколько недостатков. Поскольку поля могут быть прочитаны и записаны, пользователь не может запретить запись в поля. Вы можете применить readonly
ключевое слово, но таким образом, вы должны инициализировать поля только для чтения только в конструкторе. Более того, ничто не мешает вам хранить недопустимые значения в ваших полях.
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
Код действителен, все назначения будут выполнены, хотя они нелогичны. Age
имеет отрицательное значение, YearOfBirth
находится в далеком будущем и не соответствует возрасту и FullName
является нулевым. С полями вы не можете запретить пользователям class Name
делать такие ошибки.
Вот код со свойствами, которые решают эти проблемы.
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
Обновленная версия класса имеет следующие преимущества.
FullName
и YearOfBirth
проверяются на недопустимые значения.Age
не для записи. Это исчисляется с YearOfBirth
текущего года.FullNameInUppercase
преобразуется FullName
в верхний регистр. Это немного надуманный пример использования свойств, где свойства обычно используются для представления значений полей в формате, более подходящем для пользователя - например, с использованием текущей локали на определенном числовом DateTime
формате.Кроме того, свойства могут быть определены как виртуальные или переопределенные - просто потому, что они являются обычными .NET-методами. Для таких методов свойств применяются те же правила, что и для обычных методов.
C # также поддерживает индексаторы, которые являются свойствами, у которых есть параметр индекса в методах свойств. Вот пример.
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
Начиная с C # 3.0 позволяет определять автоматические свойства. Вот пример.
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
Несмотря на то, что он class AutoProps
содержит только свойства (или выглядит так), он может хранить 2 значения, а размер объектов этого класса равен sizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 байт.
Причина этого проста. Когда вы определяете автоматическое свойство, компилятор C # генерирует автоматический код, который содержит скрытое поле и свойство с методами свойств, обращающимися к этому скрытому полю. Вот код, который производит компилятор.
Вот код, сгенерированный ILSpy из скомпилированной сборки. Класс содержит сгенерированные скрытые поля и свойства.
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}
Итак, как вы можете видеть, компилятор по-прежнему использует поля для хранения значений - поскольку поля являются единственным способом хранения значений в объектах.
Итак, как вы можете видеть, хотя свойства и поля имеют одинаковый синтаксис использования, они представляют собой совершенно разные понятия. Даже если вы используете автоматические свойства или события - скрытые поля генерируются компилятором, в котором хранятся реальные данные.
Если вам нужно сделать значение поля доступным для внешнего мира (пользователей вашего класса), не используйте открытые или защищенные поля. Поля всегда должны быть помечены как частные. Свойства позволяют вам выполнять проверку значений, форматирование, преобразования и т. Д. И, как правило, делают ваш код более безопасным, более читаемым и расширяемым для будущих изменений.
Если вы собираетесь использовать потоковые примитивы, вы вынуждены использовать поля. Свойства могут сломать ваш многопоточный код. Кроме того, то, что сказал Кори, правильно.
(Это действительно должен быть комментарий, но я не могу опубликовать комментарий, поэтому, пожалуйста, извините, если он не подходит как сообщение).
Однажды я работал в месте, где рекомендуемой практикой было использование открытых полей вместо свойств, когда эквивалентное свойство def просто обращалось к полю, как в:
get { return _afield; }
set { _afield = value; }
Их аргументация заключалась в том, что публичное поле может быть преобразовано в собственность позже в будущем, если потребуется. В то время это казалось мне немного странным. Судя по этим постам, похоже, что не многие здесь согласятся. Что вы могли бы сказать, чтобы попытаться что-то изменить?
Редактировать: я должен добавить, что вся база кода в этом месте была скомпилирована одновременно, поэтому они могли подумать, что изменение открытого интерфейса классов (путем изменения открытого поля для свойства) не было проблемой.
Технически, я не думаю, что есть разница, потому что свойства - это просто обертки вокруг полей, созданных пользователем или автоматически созданных компилятором. Цель свойств - обеспечить инкапсуляцию и предложить облегченную функцию, похожую на метод. Это просто плохая практика объявлять поля как общедоступные, но это не имеет никаких проблем.
Поля - это обычные переменные-члены или экземпляры класса. Свойства - это абстракция для получения и установки своих значений . Свойства также называются средствами доступа, потому что они предлагают способ изменить и извлечь поле, если вы выставите поле в классе как личное. Как правило, вы должны объявить свои переменные-члены частными, а затем объявить или определить свойства для них.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
Свойства инкапсулируют поля, что позволяет вам выполнять дополнительную обработку значения, которое нужно установить или получить. Обычно излишне использовать свойства, если вы не будете выполнять предварительную или постобработку значения поля.
IMO, свойства - это просто пары функций / методов / интерфейсов "SetXXX ()" "GetXXX ()", которые мы использовали ранее, но они более лаконичны и элегантны.
когда у вас есть класс, который "Автомобиль". Свойства цвета, формы ..
Где поля - это переменные, определенные в области видимости класса.
Из Википедии - Объектно-ориентированное программирование :
Объектно-ориентированное программирование (ООП) - это парадигма программирования, основанная на концепции «объектов», которые представляют собой структуры данных, которые содержат данные в форме полей , часто называемых атрибутами; и код в форме процедур, часто называемых методами . (выделение добавлено)
Свойства на самом деле являются частью поведения объекта, но предназначены для того, чтобы предоставить потребителям объекта иллюзию / абстракцию работы с данными объекта.
Мой дизайн поля состоит в том, что поле должно быть изменено только его родителем, следовательно, классом. В результате переменная становится закрытой, чтобы иметь возможность дать право читать классы / методы за ее пределами, я прохожу через систему свойств только с Get. Затем поле извлекается свойством и доступно только для чтения! Если вы хотите изменить его, вы должны пройти через методы (например, конструктор), и я считаю, что благодаря этому способу обеспечения вашей безопасности мы можем лучше контролировать наш код, потому что мы «отбираем». Можно было бы всегда все обнародовать, поэтому каждый возможный случай, понятие переменных / методов / классов и т. Д. ... на мой взгляд, это всего лишь помощь в разработке, поддержке кода. Например, если человек возобновляет код с открытыми полями, он может делать что угодно и, следовательно, что-то «нелогичное» по отношению к цели, логика того, почему код был написан. Это моя точка зрения.
Когда я использую классические модели приватных полей / общедоступных свойств только для чтения, для 10 приватных полей я должен написать 10 публичных свойств! Код может быть действительно большим быстрее. Я обнаружил частный установщик, и теперь я использую только общедоступные свойства с частным установщиком. Сеттер создает в фоновом режиме приватное поле.
Вот почему мой старый классический стиль программирования был:
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
Мой новый стиль программирования:
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
Подумайте об этом: у вас есть комната и дверь, чтобы войти в эту комнату. Если вы хотите проверить, как кто входит и обезопасить вашу комнату, то вы должны использовать свойства, иначе они не будут никакой дверью, и каждый легко войдет без каких-либо правил.
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
Люди попадают в раздел Один довольно легко, не было никакой проверки
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
Теперь вы проверили человека и знаете, есть ли у него что-то плохое с ним
Поля являются переменными в классах. Поля - это данные, которые вы можете инкапсулировать с помощью модификаторов доступа.
Свойства похожи на поля в том, что они определяют состояния и данные, связанные с объектом.
В отличие от поля свойство имеет специальный синтаксис, который контролирует, как человек читает данные и записывает данные, они известны как операторы get и set. Заданная логика часто может использоваться для проверки.
Свойства - это особый вид члена класса. В свойствах мы используем предопределенный метод Set или Get. Они используют методы доступа, с помощью которых мы можем читать, записывать или изменять значения приватных полей.
Например, давайте возьмем класс с именем Employee
, с закрытыми полями для имени, возраста и Employee_Id. Мы не можем получить доступ к этим полям извне класса, но мы можем получить доступ к этим частным полям через свойства.
Почему мы используем свойства?
Делать поле класса общедоступным и показывать его рискованно, так как вы не будете контролировать, что будет назначено и возвращено.
Чтобы понять это на примере, давайте возьмем класс ученика, у которого есть ID, пароль, имя. Теперь в этом примере некоторые проблемы с открытым полем
Чтобы устранить эту проблему, мы используем метод Get и Set.
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
Теперь мы возьмем пример метода get и set
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
Дополнительная информация: По умолчанию методы доступа get и set доступны так же, как и само свойство. Вы можете контролировать / ограничивать доступ к средствам доступа индивидуально (для получения и установки), применяя к ним более ограничивающие модификаторы доступа.
Пример:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Здесь get все еще общедоступен (так как свойство общедоступно), но set защищен (более ограниченный спецификатор доступа).
Свойства используются для выставления поля. Они используют методы доступа (set, get), через которые можно читать, записывать или манипулировать значениями приватных полей.
Свойства не называют места хранения. Вместо этого у них есть средства доступа, которые читают, записывают или вычисляют свои значения.
Используя свойства, мы можем установить проверку типа данных, заданных для поля.
Например, у нас есть частное целое поле возраста, на котором мы должны разрешить положительные значения, так как возраст не может быть отрицательным.
Мы можем сделать это двумя способами, используя getter и setters и используя свойство.
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
Автоматически реализованное свойство Если мы не используем логику в методах get и set, мы можем использовать автоматически реализованное свойство.
При использовании автоматически реализуемых свойств компиляция создает частное анонимное поле, к которому можно получить доступ только через методы доступа get и set.
public int Age{get;set;}
Абстрактные свойства Абстрактный класс может иметь абстрактное свойство, которое должно быть реализовано в производном классе
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Мы можем приватно установить свойство. В этом мы можем приватно установить свойство auto (устанавливается с помощью класса).
public int MyProperty
{
get; private set;
}
Вы можете достичь того же с помощью этого кода. В этом наборе свойств функция недоступна, так как мы должны установить значение для поля напрямую.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
В подавляющем большинстве случаев это будет имя свойства, к которому вы обращаетесь, а не имя переменной ( поле ). Причина этого заключается в том, что он считается хорошей практикой в .NET и в C #, в частности, для защиты каждого фрагмента данных в классе будь то переменная экземпляра или статическая переменная (переменная класса), потому что она связана с классом.
Защитите все эти переменные с соответствующими свойствами, которые позволяют вам определять, устанавливать и получать методы доступа и выполнять такие вещи, как проверка, когда вы манипулируете этими частями данных.
Но в других случаях, таких как класс Math (пространство имен System), в класс встроено несколько статических свойств. одна из которых является математической константой PI
например. Math.PI
и поскольку PI является частью данных, которые четко определены, нам не нужно иметь несколько копий PI, это всегда будет одно и то же значение. Таким образом, статические переменные иногда используются для обмена данными между объектами класса, но они также обычно используются для постоянной информации, когда вам нужна только одна копия фрагмента данных.