Разница между свойством и полем в С# 3.0+ - программирование

Разница между свойством и полем в С# 3.0+

Я понимаю, что это дубликат В чем разница между полем и свойством в С#?, но мой вопрос имеет небольшую разницу (из моего точка зрения):

Как только я знаю, что

  • Я не буду использовать свой класс с "методами, которые работают только с свойствами" и
  • Я не буду использовать код проверки в getter/setter.

Есть ли какая-либо разница (кроме стиля/будущего развития), как какой-то тип управления при настройке свойства?

Есть ли дополнительная разница между:

public string MyString { get; set; }

и

public string myString;

(Я знаю, что для первой версии требуется С# 3.0 или выше и что компилятор создает частные поля.)

4b9b3361

Ответ 1

Герметизация.

Во втором случае вы только что определили переменную, во-первых, у этой переменной есть геттер/сеттер. Поэтому, если вы решите, что хотите подтвердить эту переменную на более позднюю дату, это будет намного проще.

Плюс они проявляются по-разному в Intellisense:)

Изменить: Обновление для обновленного вопроса OPs - если вы хотите проигнорировать другие предложения здесь, другая причина в том, что это просто не хороший дизайн OO. И если у вас нет веских оснований для этого, всегда выберите свойство над общедоступной переменной/полем.

Ответ 2

Поля и свойства выглядят одинаково, но это не так. Свойства являются методами и как таковые существуют определенные вещи, которые не поддерживаются для свойств, и некоторые вещи, которые могут произойти со свойствами, но никогда в случае полей.

Вот список отличий:

  • Поля могут использоваться как входные аргументы out/ref. Свойства не могут.
  • Поле всегда будет давать тот же результат при вызове несколько раз (если мы оставим проблемы с несколькими потоками). Свойство, такое как DateTime.Now, не всегда равно самому себе.
  • Свойства могут вызывать исключения - поля никогда этого не сделают.
  • Свойства могут иметь побочные эффекты или выполнять действительно долгое время. Поля не имеют побочных эффектов и всегда будут такими же быстрыми, как можно ожидать для данного типа.
  • Свойства поддерживают различную доступность для геттеров/сеттеров - полей нет (но поля могут быть сделаны readonly)
  • При использовании отражения свойства и поля рассматриваются как разные MemberTypes, поэтому они расположены по-разному (GetFields vs GetProperties например)
  • Компилятор JIT может обрабатывать доступ к свойствам по-разному по сравнению с доступом к полям. Однако он может скомпилироваться с идентичным нативным кодом, но область различий существует.

Ответ 3

Несколько быстрых, очевидных различий

  • Свойство может иметь ключевые слова для доступа.

    public string MyString { get; private set; }
    
  • Свойство может быть переопределено в потомках.

    public virtual string MyString { get; protected set; }
    

Ответ 4

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

Ответ 5

Аксессоры - это больше, чем поля. Другие уже отметили несколько важных отличий, и я собираюсь добавить еще один.

Свойства участвуют в интерфейсных классах. Например:

interface IPerson
{
    string FirstName { get; set; }
    string LastName { get; set; }
}

Этот интерфейс может быть выполнен несколькими способами. Например:

class Person: IPerson
{
    private string _name;
    public string FirstName
    {
        get
        {
            return _name ?? string.Empty;
        }
        set
        {
            if (value == null)
                throw new System.ArgumentNullException("value");
            _name = value;
        }
    }
    ...
}

В этой реализации мы защищаем как класс Person от попадания в недопустимое состояние, так и вызывающий из получателя null из непризнанного свойства.

Но мы могли бы продвинуть дизайн еще дальше. Например, интерфейс может не работать с установщиком. Достаточно законно говорить, что потребители интерфейса IPerson интересуются только тем, чтобы получить свойство, а не устанавливать его:

interface IPerson
{
    string FirstName { get; }
    string LastName { get; }
}

Предыдущая реализация класса Person удовлетворяет этому интерфейсу. Тот факт, что он позволяет вызывающему абоненту также устанавливать свойства, не имеет смысла с точки зрения потребителей (которые потребляют IPerson). Дополнительные функциональные возможности конкретной реализации учитываются, например, построителем:

class PersonBuilder: IPersonBuilder
{
    IPerson BuildPerson(IContext context)
    {

        Person person = new Person();

        person.FirstName = context.GetFirstName();
        person.LastName = context.GetLastName();

        return person;

    }
}

...

void Consumer(IPersonBuilder builder, IContext context)
{
    IPerson person = builder.BuildPerson(context);
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}

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

Еще одна вполне допустимая реализация IPerson будет непреложным классом человека и соответствующим человеком factory:

class Person: IPerson
{
    public Person(string firstName, string lastName)
    {

        if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
            throw new System.ArgumentException();

        this.FirstName = firstName;
        this.LastName = lastName;

    }

    public string FirstName { get; private set; }

    public string LastName { get; private set; }

}

...

class PersonFactory: IPersonFactory
{
    public IPerson CreatePerson(string firstName, string lastName)
    {
        return new Person(firstName, lastName);
    }
}
...
void Consumer(IPersonFactory factory)
{
    IPerson person = factory.CreatePerson("John", "Doe");
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}

В этом примере кода потребитель снова не знает о заполнении свойств. Потребитель имеет дело только с геттерами и конкретной реализацией (а бизнес-логика позади него, например, тестирование, если имя пуста) предоставляется специализированным классам - строителям и фабрикам. Все эти операции совершенно невозможны с полями.

Ответ 6

Первый:

public string MyString {get; set; }

- свойство; второй (public string MyString) обозначает поле.

Разница в том, что некоторые методы (привязка данных к ASP.NET для экземпляров) работают только на свойствах, а не на полях. То же самое верно для XML-сериализации: только свойства сериализованы, поля не сериализованы.

Ответ 7

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

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

Подумайте о свойствах как синтаксическом сахаре для функций getXXX()/setXXX(). Вот как они реализованы за кулисами.

Ответ 8

Существует еще одно важное различие между полями и свойствами.

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

Ответ 9

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