Что в 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 указывает, что вы также можете выполнять другую логику, такую как проверка, при доступе к свойству, еще одна полезная функция.
Стоит отметить, что свойства не требуются для инкапсуляции полей. За имуществом вообще не могло быть поля. Это может быть вычисление, возврат константы или что-то еще.
«при этом не влияя на внешний способ доступа к ним вещей, которые используют ваш класс». Простите меня, если я неправильно понимаю, но зачем вообще нужны модификаторы доступа перед свойствами, если поле позади них, кажется, справляется с этим? т.е. зачем делать собственность чем-то еще, кроме публичного?
@Chucky Я задал аналогичный вопрос на Java, который может применяться здесь. Вопрос
Чтобы добавить к «полноте» обсуждения, мы отличаем свойство от поля, говоря, что свойство является абстракцией первого (но не обязательно, как отмечает Кент). В нашем контексте поле и атрибут взаимозаменяемы?
Ваш ответ был прямо перед правками и ошибочными комментариями, за которые проголосовали как ни странно. Свойство всегда должно инкапсулировать одно или несколько полей и никогда не должно выполнять тяжелую работу или проверку. Если вам нужно такое свойство, как UserName или Password, для проверки, измените их тип со строк на Объекты-значения. Между создателем класса и потребителем существует негласный договор. Поля содержат состояние, свойства отображают состояние с использованием одного или нескольких полей, пустоты изменяют состояние (тяжелая работа), а функции выполняют запросы (тяжелая работа). Это не камень, а просто ожидания.
@KentBoogaart - Без инкапсуляции полей у свойства будет одна из нескольких возможностей: get { return "hello"; }. Или функции: get { return someFunction(); }. Почему бы просто не создать константы и функции? Просто чтобы потребителям не нужно было поставлять ()? Потребитель должен верить, что вызов () означает, что может потребоваться налоговая работа, а вызов недвижимости означает, что работа по налогам не будет взиматься. И когда сеттер не изменит состояние объекта (следовательно, изменит поле). Я понимаю, что вы МОЖЕТЕ делать эти вещи, но, конечно, не должны обсуждаться публично.
@Suamere Почему сеттер не должен выполнять валидацию?
@jpaugh Если я потребитель класса, я следую контрактам, установленным создателем класса. Если свойство - string, мой контракт таков: назначить любые символы длиной до ~ 2 млрд. Если свойство - DateTime, мой контракт таков: назначать любые числа в пределах DateTime, которые я могу найти. Если создатель добавляет ограничения к установщикам, эти ограничения не передаются. Но если вместо этого создатель изменяет тип с string на Surname, тогда их новый класс Surname сообщает ограничения, а свойство public Surname LastName не имеет проверки установщика. Кроме того, Surname можно использовать повторно.
А поскольку Surname, в моем примере, можно использовать повторно, вам не нужно беспокоиться о последующем копировании / вставке этих проверок в установщике свойств в другие места кода. Не удивительно, если проверка фамилии происходит в нескольких местах, если вы когда-нибудь вносите изменения в бизнес-правила для фамилий. Посмотрите ссылку, которую я опубликовал о Value Objects.
@Suamere Ввод логики проверки в сеттер обеспечивает другой контракт: объект никогда не может перейти в недопустимое состояние по отношению к. проверенные свойства. Когда все методы доступа проверены (при необходимости) и поля не отображаются без такой проверки, этот контракт, который я назову «Настройка никогда не вызывает сбой объекта», часто оказывается более полезным, чем «настройка никогда не дает сбоев». Действительно ли Любые такой контракт передается без чтения источника? Нет, не совсем. Это скорее часть свойства; только поведение поля имеет такую прозрачность.
@jpaugh Ты на правильном пути туда, где я стою. Вы говорите «нет», о контрактах никогда не сообщают без ознакомления с источником. Но контракты легко сообщаются, а проверка легко реализуется, если вы используете Объекты-значения, как я уже упоминал, и поэтому мы вернулись к исходной точке, в которой я нахожусь.
@Suamere Ты не говоришь? Haskell имеет встроенную поддержку таких «оболочек типов только для контрактов» (и называет их newtypes), но я сам не рассматривал возможность их реализации на языке объектно-ориентированного программирования. (Спасибо!) В Haskell они не добавляют никаких накладных расходов во время выполнения, что приятно: "после того, как тип проверяется во время компиляции, во время выполнения {newtype wrapper} может обрабатываться практически так же, без накладных расходов или косвенного обращения, обычно связанных ..."
По этому вопросу, а также по поводу информации, представленной в ответе, и содержания комментариев ведется много дискуссий. По этому вопросу было бы неплохо обратиться к документации: docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
Это не решает вопрос. Вопрос в том, «в чем разница ...», в этом посте говорится: «вместо того, чтобы рассказать вам, в чем разница, я говорю вам, как вы должны работать»
Принципы объектно-ориентированного программирования гласят, что внутренняя работа класса должна быть скрыта от внешнего мира. Если вы открываете поле, вы, по сути, раскрываете внутреннюю реализацию класса. Поэтому мы заключаем поля в свойства (или методы в случае 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
}
+1 за упоминание автосвойств - я думаю, что это то, что многие из ответов здесь (и в других местах) забыли внести. Без этого объяснения все еще может быть довольно сложно понять, что на самом деле означает public int myVar { get; set; } (и я предполагаю, что это причина не менее 50% ответов на этот вопрос).
+1 также за упоминание auto и упоминания о том, как это работает («AutoProperty создает для нас частное поле»). Это был ответ, который я искал на свой вопрос. При исследовании я не увидел на странице MSDN о них никаких указаний на то, что было создано частное поле, которое вызывало путаницу. Думаю, вот что это значит? «Атрибуты разрешены в автоматически реализуемых свойствах, но, очевидно, не в поддерживающих полях, поскольку они недоступны из исходного кода. Если вы должны использовать атрибут в поддерживающем поле свойства, просто создайте обычное свойство». но не был уверен.
Обратите внимание, что в данном примере приседания не рассматриваются. Это свойство дает 100% полный доступ к закрытому полю, так что оно вообще не объектно-ориентировано. В этом случае у вас также может быть публичное поле. Конечно, это помогает (незначительно) рефакторингу кода в будущем, но любая достойная IDE IDE может преобразовать поле в свойство с помощью нескольких нажатий клавиш. Ответ может быть технически правильным относительно того, как работают свойства, но он не дает хорошего «ООП-объяснения» их использованию.
@kai Я согласен с тем, что ответ слишком упрощен и не показывает всю мощь авто-свойства, однако я не согласен с тем, что это не объектно-ориентированный подход. Вы можете захотеть проверить разницу между полями и свойствами. Поля не могут быть виртуальными, а virtual сам является частью объектно-ориентированного программирования.
Конечно, есть некоторая функциональная разница. Я бы не стал называть virtual ООП как таковым. Это инструмент, который включает полиморфизм, который является одним из ключевых инструментов, ВКЛЮЧАЮЩИХ ООП. Это не ООП само по себе, и в публичном автосвойстве по сути нет ничего ООП. Я бы не стал считать такие вещи, как отражение или привязка данных к ООП. Обычно я не был бы настолько педантичен, но в ответе конкретно упоминались принципы объектно-ориентированного программирования как движущая сила примера кода, и я не согласен с этим.
@sara "Это свойство дает 100% полный доступ к закрытому полю, поэтому оно вообще не объектно-ориентировано." Вы упускаете суть. Инкапсуляция заключается в том, что потребитель объекта не знает, как разрешается значение. В случае собственности поле - одна из возможностей. Это может быть файл cookie вместо поля.
Это не решает вопрос. Вопрос в том, «в чем разница ...», в этом посте говорится: «вместо того, чтобы рассказать вам, в чем разница, я говорю вам, как вы должны работать»
Если вы собираетесь использовать примитивы потоков, вам придется использовать поля. Свойства могут нарушить ваш многопоточный код. В остальном то, что сказал Кори, верно.
с каких пор? заблокируйте свое вспомогательное поле в пределах собственности, и это эквивалент
Свойства - это методы, и сегодня они не встраиваются ни в какой CIL JIT. Если вы собираетесь использовать примитивы потоков, такие как Interlocked, вам нужны поля. Проверьте свои источники. По общему признанию, «запирать» было неправильным словом.
Свойства инкапсулируют поля, что позволяет выполнять дополнительную обработку значения, которое нужно установить или получить. Обычно использование свойств является излишним, если вы не будете выполнять предварительную или постобработку значения поля.
нет, я всегда использую свойства, это позволяет вам гибко изменять реализацию в любое время без нарушения вашего API.
Что касается эволюции API, вы можете без проблем использовать поля для данных частный. Также в нечетных случаях, когда вы хотите поделиться данными внутри сборки, вы можете предоставить полям «внутренний» доступ.
Основное преимущество свойств заключается в том, что они позволяют изменять способ доступа к данным объекта, не нарушая его общедоступный интерфейс. Например, если вам нужно добавить дополнительную проверку или изменить сохраненное поле на вычисляемое, вы можете легко это сделать, если изначально выставили поле как свойство. Если вы просто открыли поле напрямую, вам придется изменить публичный интерфейс вашего класса, чтобы добавить новые функции. Это изменение нарушит работу существующих клиентов и потребует их перекомпиляции, прежде чем они смогут использовать новую версию вашего кода.
Если вы напишете библиотеку классов, предназначенную для широкого использования (например, .NET Framework, которую используют миллионы людей), это может стать проблемой. Однако, если вы пишете класс, используемый внутри небольшой базы кода (скажем, <= 50 тыс. Строк), на самом деле это не имеет большого значения, потому что ваши изменения никого не коснутся. В этом случае все сводится к личным предпочтениям.
Кроме того, свойства позволяют использовать логику при установке значений.
Таким образом, вы можете сказать, что хотите установить значение только для целочисленного поля, если значение больше x, иначе вызовите исключение.
Действительно полезная функция.
В фоновом режиме свойство компилируется в методы. Таким образом, свойство Name компилируется в get_Name() и set_Name(string value). Вы можете убедиться в этом, если изучите скомпилированный код.
Таким образом, при их использовании возникают (очень) небольшие накладные расходы на производительность. Обычно вы всегда будете использовать свойство, если вы открываете поле снаружи, и вы часто будете использовать его внутри, если вам нужно выполнить проверку значения.
Свойства поддерживают асимметричный доступ, то есть у вас могут быть либо геттер и сеттер, либо только один из двух. Точно так же свойства поддерживают индивидуальную доступность для геттеров / сеттеров. Поля всегда симметричны, т.е. всегда можно как получить, так и задать значение. Исключением являются поля только для чтения, которые, очевидно, не могут быть установлены после инициализации.
Свойства могут работать очень долго, иметь побочные эффекты и даже вызывать исключения. Поля работают быстро, без побочных эффектов и никогда не вызывают исключений. Из-за побочных эффектов свойство может возвращать разные значения для каждого вызова (как это может быть в случае DateTime.Now, т.е. DateTime.Now не всегда равно DateTime.Now). Поля всегда возвращают одно и то же значение.
Поля могут использоваться для параметров out / ref, свойства - нет. Свойства поддерживают дополнительную логику - это может быть использовано, среди прочего, для реализации отложенной загрузки.
Свойства поддерживают уровень абстракции, инкапсулируя все, что означает получение / установка значения.
Используйте свойства в большинстве / во всех случаях, но старайтесь избегать побочных эффектов.
Поля могут иметь все проблемы стоимости свойств, когда тип данных поля является объектом с перегрузкой оператора преобразования - это тонкая проблема.
Свойства никогда не должны иметь побочных эффектов. Даже отладчик предполагает, что может безопасно их оценить.
@Strilanc: Я полностью согласен, однако это не всегда так. Что касается отладчика, с FuncEval есть много проблем, если вы об этом говорите.
Важное отличие состоит в том, что интерфейсы могут иметь свойства, но не поля. Для меня это подчеркивает, что свойства должны использоваться для определения открытого интерфейса класса, в то время как поля предназначены для использования в частной внутренней работе класса. Как правило, я редко создаю общедоступные поля, и точно так же я редко создаю закрытые свойства.
Любопытно, какие могут быть эти редкие сценарии!
Этот ответ и ответы ниже верны. 2 сообщения с наибольшим количеством голосов не отвечают на вопрос. Вопрос в том, «в чем разница ...», но ответы, получившие наибольшее количество голосов, отвечают «вместо того, чтобы рассказывать вам, в чем разница, я говорю вам, как вы должны работать»
Я дам вам пару примеров использования свойств, которые могут заставить шестерни вращаться:
Вопрос о грязном отслеживании: что, если бы я мог изменить поле напрямую - я не знаю, можно ли это сделать, я мог бы сказать: «объект не нужно сохранять, если ни одно ПОЛЕ объекта не изменилось» Таким образом, грязное отслеживание не будет иметь значения, я что-то упускаю?
@juanpastas: Преимущество свойств в отношении грязного отслеживания заключается в том, что если установщики свойств установят «грязный» флаг, то в сценарии, где этот флаг не установлен, коду не нужно будет проверять значения каких-либо свойств, чтобы увидеть если бы они могли измениться. Напротив, если объект предоставляет свои атрибуты как поля, тогда содержимое всех полей должно сравниваться с предыдущим значением (что не только добавляет время для сравнения, но также означает, что код должен имеют предыдущее значение).
Это хороший вариант. Он также позволяет запускать методы (как события) или вести журнал при установке или считывании значения.
(Это действительно должен быть комментарий, но я не могу опубликовать комментарий, поэтому, пожалуйста, извините, если он не подходит для публикации).
Однажды я работал в месте, где рекомендовалось использовать общедоступные поля вместо свойств, когда эквивалентное свойство def просто обращалось к полю, как в:
get { return _afield; }
set { _afield = value; }
Их аргументация заключалась в том, что публичное поле может быть преобразовано в собственность позже, если потребуется. Тогда мне это показалось немного странным. Судя по этим постам, похоже, что и здесь не многие согласятся. Что вы могли бы сказать, чтобы попытаться что-то изменить?
Обновлено: я должен добавить, что вся база кода в этом месте была скомпилирована одновременно, поэтому они могли подумать, что изменение открытого интерфейса классов (путем изменения общедоступного поля на свойство) не было проблемой.
Начиная с C# 3.0, описанный здесь шаблон удобно поддерживается функцией под названием Автореализуемые свойства.
Я считаю одним из преимуществ C# со свойствами, поскольку они имеют тот же API, что и поля, поэтому клиентам этого класса на самом деле все равно, обращаются ли они к свойству или полю. (Это НЕ верно, например, в C++). Я считаю, что при создании прототипов разумно начинать с общедоступных полей, а затем при необходимости переходить к свойствам. Свойства снижают производительность и память, а также требуется дополнительная типизация. Они не бесплатны. Но, если вы передумаете, вам не нужно будет реорганизовывать какой-либо зависимый код.
Свойства нельзя использовать в качестве параметров OUT или REF, поэтому изменение поля в свойство может привести к ошибкам компиляции в дальнейшем. Если бы значение было реализовано как свойство с самого начала, то оно никогда не использовалось бы в качестве параметров OUT или REF (VAR в Pascal / Delphi), и любое изменение, которое вы вносите в геттер / сеттер, было бы прозрачным для использования.
Используя свойства, вы можете инициировать событие, когда значение свойства изменяется (также известное как 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);
}
}
Мне потребовалось много времени, чтобы это найти. Это MVVM. Спасибо ! :)
поле - это переменная, объявленная непосредственно в классе или структуре. Класс или структура могут иметь поля экземпляра или статические поля или и то, и другое. Как правило, следует использовать поля только для переменных, которые имеют частную или защищенную доступность. Данные, которые ваш класс предоставляет клиентскому коду должны быть предоставлены через методы, свойства и индексаторам. Используя эти конструкции для косвенного доступа к внутренним полям, вы можете защититься от недопустимых входных значений.
имущество - это член, который предоставляет гибкий механизм для чтения, записи или вычисления значения частного поля. Свойства можно использовать, как если бы они были членами общедоступных данных, но на самом деле они являются специальными методами, называемыми аксессуары. Это позволяет легко получить доступ к данным и при этом способствует продвижению безопасность и гибкость методов. Свойства позволяют классу предоставлять публичный способ получения и установки значений, скрывая при этом код реализации или проверки. Метод доступа get свойства используется для возврата значения свойства, а метод доступа set используется для присвоения нового значения.
Это отличный ответ, действительно помог мне понять это.
«Свойство - это элемент, который предоставляет гибкий механизм для чтения, записи или вычисления значения частного поля». В этом есть смысл.
Технически я не думаю, что есть разница, потому что свойства - это просто оболочки вокруг полей, созданных пользователем или автоматически созданных компилятором. Цель свойств - обеспечить инкапсуляцию и предложить облегченную функцию, подобную методам. Объявлять поля общедоступными - это просто плохая практика, но в этом нет никаких проблем.
IMO, Свойства - это просто пары функций / методов / интерфейсов «SetXXX ()» «GetXXX ()», которые мы использовали раньше, но они более лаконичны и элегантны.
Если вы хотите, чтобы ваша частная переменная (поле) была доступна для объекта вашего класса из других классов, вам необходимо создать свойства для этих переменных.
например, если у меня есть переменные с именами «id» и «name», которые являются частными но может возникнуть ситуация, когда эта переменная понадобится для операции чтения / записи вне класса. В этой ситуации свойство может помочь мне получить эту переменную для чтения / записи в зависимости от заданных для свойства get / set. Свойство может быть как только для чтения, так и только для записи / чтения и записи.
вот демо
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";
}
}
Поскольку многие из них объяснили технические плюсы и минусы 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. Почему??? Потому что Properties может принимать Атрибуты. Не отображается, если значение [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. В источнике привязки можно использовать только свойства.
Источник привязки помогает нам уменьшить количество строк кода. 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;
}
}
Это интересные факты, но вы упускаете из виду философию полей и свойств.
Что вы имеете в виду под ФИЛОСОФИЯ? @Dawid Ferenczy
См., Например, отмеченный ответ. Но вы заметили, что вы просто приводите примеры использования, так как разница между полями и свойствами уже была описана, поэтому забыли мой комментарий, пожалуйста :)
Я читал это, но вы явно не читали мой предыдущий комментарий: «Но вы заметили, что вы просто приводите примеры использования, так как разница между полями и свойствами уже была описана, поэтому забыли мой комментарий, пожалуйста :)».
Традиционно частные поля устанавливаются с помощью методов получения и установки. Ради меньшего количества кода вы можете вместо этого использовать свойства для установки полей.
когда у вас есть класс «Автомобиль». Свойства цвет, форма ..
Где as поля - это переменные, определенные в рамках класса.
Поля - это обычные переменные-члены или экземпляры-члены класса. Свойства - это абстракция для получения и установки их значений. Свойства также называются аксессорами, потому что они предлагают способ изменить и получить поле, если вы предоставляете поле в классе как частное. Как правило, вы должны объявить свои переменные-члены частными, а затем объявить или определить для них свойства.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
Второй вопрос здесь, «когда следует использовать поле вместо свойства?», Лишь кратко затронут в этот другой ответ и вроде как это тоже, но не очень подробно.
В общем, все остальные ответы точно говорят о хорошем дизайне: лучше раскрывать свойства, а не поля. Хотя вы, вероятно, не заметите, что регулярно скажет «вау, представьте, насколько хуже было бы, если бы я сделал это поле вместо свойства», так много реже вспоминает ситуацию, когда вы бы сказали «вау, спасибо Боже, я использовал здесь поле вместо собственности. "
Но есть одно преимущество полей перед свойствами, а именно их способность использоваться в качестве параметров «ref» / «out». Предположим, у вас есть метод со следующей подписью:
public void TransformPoint(ref double x, ref double y);
и предположим, что вы хотите использовать этот метод для преобразования массива, созданного следующим образом:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Я думаю, что это самый быстрый способ сделать это, поскольку Икс и 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 может быть полезна, например, при вызове семейства методов Заблокирован или Летучий. Примечание. Если это новость для вас, Volatile - это, по сути, способ добиться того же поведения, которое обеспечивается ключевым словом volatile. Таким образом, как и volatile, он не решает волшебным образом всех проблем с поточной безопасностью, как предполагает его название.
Я определенно не хочу показаться, что я защищаю, чтобы вы сказали: «О, я должен начать раскрывать поля вместо свойств». Дело в том, что если вам нужно регулярно использовать эти члены в вызовах, которые принимают параметры «ref» или «out», особенно для чего-то, что может быть простым типом значения, которому вряд ли когда-либо понадобится какой-либо из дополнительных элементов свойств, можно привести аргумент.
Из Википедии - Объектно-ориентированное программирование:
Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which are data structures that contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods. (emphasis added)
Свойства на самом деле являются частью поведения объекта, но предназначены для того, чтобы дать потребителям объекта иллюзию / абстракцию работы с данными объекта.
Свойства - это особый вид члена класса. В свойствах мы используем предопределенный метод Set или Get. Они используют средства доступа, с помощью которых мы можем читать, записывать или изменять значения частных полей.
Например, возьмем класс с именем Employee с частными полями для имени, возраста и Employee_Id. Мы не можем получить доступ к этим полям извне класса, но мы можем получить доступ к этим частным полям через свойства.
Почему мы используем свойства?
Делать поле класса общедоступным и раскрывать его рискованно, так как у вас не будет контроля над тем, что назначается и возвращается.
Чтобы ясно понять это на примере, давайте возьмем класс студентов, у которых есть идентификатор, пароль и имя. Теперь в этом примере проблема с общедоступным полем
Чтобы устранить эту проблему, мы используем метод Get and 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. Затем поле извлекается свойством и доступно только для чтения! Если вы хотите изменить его, вам нужно пройти через методы (например, конструктор), и я считаю, что благодаря этому способу обеспечения вашей безопасности мы лучше контролируем наш код, потому что мы «фланжируем». Можно очень хорошо всегда публиковать все, поэтому каждый возможный случай, понятие переменных / методов / классов и т.д ... на мой взгляд, это просто помощь в разработке, поддержании кода. Например, если человек возобновляет код с общедоступными полями, он может делать все, что угодно, и, следовательно, вещи «нелогичны» по отношению к цели, логике того, почему был написан код. Это моя точка зрения.
Когда я использую классическую модель частного поля / общедоступных свойств только для чтения, для 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;
}
}
Да уж плохо, извини!
Дополнительная информация: По умолчанию методы доступа get и set доступны так же, как и само свойство. Вы можете контролировать / ограничивать доступность средств доступа индивидуально (для получения и установки), применяя к ним более ограничивающие модификаторы доступа.
Пример:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Здесь get по-прежнему общедоступен (поскольку свойство является общедоступным), но set защищен (более ограниченный спецификатор доступа).
Свойства используются для раскрытия поля. Они используют методы доступа (set, get), с помощью которых значения частных полей могут быть прочитаны, записаны или изменены.
В свойствах не указываются места хранения. Вместо этого у них есть средства доступа, которые читают, записывают или вычисляют свои значения.
Используя свойства, мы можем установить проверку типа данных, установленных в поле.
Например, у нас есть личное целочисленное поле age, в котором мы должны разрешить положительные значения, поскольку age не может быть отрицательным.
Мы можем сделать это двумя способами, используя методы получения и установки и свойство.
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()
}
}
Автореализованное свойство, если мы не логичны в методах получения и установки, мы можем использовать автоматически реализованное свойство.
Когда use автоматически реализуемое свойство компилирует создает частное анонимное поле доступен только через методы доступа 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; }
}
Подумайте об этом: у вас есть комната и дверь для входа в эту комнату. Если вы хотите проверить, кто входит, и обезопасить свою комнату, вам следует использовать свойства, иначе они не будут дверью, и каждый легко войдет без каких-либо правил.
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
Люди попадают в sectionOne довольно легко, проверки не было
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";
Теперь вы проверили человека и знаете, есть ли с ним что-то злое
В подавляющем большинстве случаев это будет имя свойства, к которому вы обращаетесь, а не имя переменной (поле). Причина в том, что это считается хорошей практикой в .NET и в C#, в частности, для защиты каждой части данных в классе. , будь то переменная экземпляра или статическая переменная (переменная класса), потому что она связана с классом.
Защитите все эти переменные соответствующими свойствами, которые позволяют вам определять установить и получитьаксессуары и делать такие вещи, как проверка, когда вы манипулируете этими частями данных.
Но в других случаях, таких как Класс математики (системное пространство имен), есть пара статических свойств, встроенных в класс. одна из которых - математическая константа ЧИСЛО ПИ
например. Math.PI
и поскольку PI - это четко определенный фрагмент данных, нам не нужно иметь несколько копий PI, это всегда будет одно и то же значение. Таким образом, статические переменные иногда используются для обмена данными между объектами класса, но также обычно используются для постоянной информации, когда вам нужна только одна копия части данных.
Поля - это переменные в классах. Поля - это данные, которые можно инкапсулировать с помощью модификаторов доступа.
Свойства похожи на поля в том, что они определяют состояния и данные, связанные с объектом.
В отличие от поля свойство имеет специальный синтаксис, который управляет тем, как человек читает данные и записывает данные, они известны как операторы get и set. Установленную логику часто можно использовать для проверки.
Основное и общее различие:
Поля
Характеристики
Привет и добро пожаловать в StackOverflow. Пожалуйста, найдите время, чтобы прочитать страницу справки, особенно разделы с названием Как ответить. Вы также можете узнать о минимальный воспроизводимый пример.
Всем привет и спасибо! Что-то не так с моим ответом? Я прочитал все предыдущие и нашел их слишком многословными. Я считаю, что моя суть различия между полями и свойствами в C#. Он как можно короче, но все же объясняет суть.
Привет, @Ted. Iw'e работал над C# около 12 лет и никогда не задумывался о побочных эффектах :) Хотел бы услышать о них. Но я согласен, ответ краткий и точный. Просто нужно немного подробнее :)
@Oddmar Dam, я их перечислил в скобках. Примером может быть это (dotnetfiddle.net/SFWC1d)
Разница четко объяснена здесь. Однако, чтобы подвести итог и выделить:
Поля инкапсулируются внутри класса для его внутренней операции, тогда как свойства могут использоваться для предоставления класса внешнему миру в дополнение к другим внутренним операциям, показанным в общей ссылке. Кроме того, если вы хотите загрузить определенные методы или пользовательские элементы управления на основе значения определенного поля, то свойство сделает это за вас:
Например:
Вы можете работать под пользовательским элементом управления на своей странице asp.net, просто присвоив значение параметру Id элемента управления на странице aspx, как показано ниже:
useMeId.Id=5 ---call the property of user control "UseMe.ascx"
UseMe.ascx
<%@ Register Src=~/"UseMe.ascx" TagPrefix = "uc" TagName = "UseMe" %>
<uc:UseMe runat = "Server" id = "useMeId" />
UseMe.ascx.cs
private int currentId;
public int Id
{
get
{
return currentId;
}
set
{
currentId = value;
LoadInitialData(currentId);
}
}
Private void LoadinitialData(int currentIdParam)
{
//your action
}
Microsoft прямо отвечает на этот вопрос (для всех языков .NET) как часть своего Рекомендации по дизайну участников. Подробности см. В статьях Дизайн недвижимости и Полевой дизайн. Обратите внимание, что существует различие между членами пример и членами статический.