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



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



Как только я это узнаю




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

  • Я не буду использовать код проверки в геттер/сеттер.


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



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



public string MyString { get; set; }


и



public string myString;


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

1032   10  

10 ответов:

инкапсуляция.

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

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

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

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

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

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

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

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

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

    public virtual string MyString { get; protected set; }
    

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

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

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

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). Дополнительная функциональность конкретной реализации учитывается, например, builder:

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 был бы неизменяемым классом человека и соответствующим человеком фабрика:

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

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

первый:

public string MyString {get; set; }

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

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

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

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

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

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

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

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

Пусть говорят, что у вас есть OnChangeproperty следующее:
public Action OnChange { get; set; }

если вы хотите использовать делегатов, чем нужно, чтобы изменить его OnChange до field такой:

public event Action OnChange = delegate {};

в такой ситуации мы защищаем наше поле от нежелательного доступа или модификации.

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

Comments

    Ничего не найдено.