Подтвердить что ты не робот

Понимание частных разработчиков

Я не понимаю необходимости иметь частные сеттеры, которые начинались с С# 2.

Наличие метода setter для меня позволяет пользователю установить некоторые переменные в этом классе. При этом мы не будем подвергать переменные напрямую пользователям. Вместо этого мы позволяем им делать это с помощью этого общедоступного метода setter.

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

Я не использую инкапсуляцию с использованием общедоступных методов настройки? Почему нам нужны частные сеттеры?

В чем разница между неизменяемым классом и классом с частными сеттерами?

4b9b3361

Ответ 1

Логически.

Наличие частного сеттера связано с тем, что вы можете использовать свойство auto:

public int MyProperty { get; set; }

Что бы вы сделали, если хотите сделать это только для чтения?

public int MyProperty { get; }

О, дерьмо!! Я не могу получить доступ к нему из своего класса; Я должен создать его как обычное свойство:

private int myProperty;
public int MyProperty { get { return myProperty; } }

Хм... но я потерял функцию "Авто свойство"...

public int MyProperty { get; private set; }

AHHH.. это лучше!!

Ответ 2

Частный сеттер полезен, если вы имеете свойство только для чтения и не хотите явно объявлять опорную переменную.

Итак:

public int MyProperty
{
    get; private set;
}

совпадает с:

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

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

Чтобы ответить на ваш последний вопрос, MSDN имеет это сказать в частных сеттерах:

Однако для небольших классов или структур, которые просто инкапсулируют набор значений (данных) и мало или вообще не имеют поведения, рекомендуется сделать объекты неизменными, объявив при этом аксессуар набора как закрытый.

От страница MSDN в свойствах Auto Implemented

Ответ 3

Это довольно просто. Частные сеттеры позволяют создавать общедоступные или защищенные свойства только для чтения.

Что это. Это единственная причина.

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

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

Ответ 4

С введением С# 6.0 и синтаксисом Инициализаторы автоисточников, частные настройки больше не нужны для свойств, которые устанавливаются только при инициализации, как внутри, так и внутри конструктора.

Эти новые синтаксисы теперь компилируются:

Встроенное инициализированное свойство

public class MyClass1 {
  public string MyProperty { get; } = "Aloha!"
}

Инициализированное конструктор

public class MyClass2 {
  public string MyProperty { get; }

  public MyClass2(string myProperty) {
    MyProperty = myProperty;
  }
}

Ответ 5

Я не понимаю необходимости иметь частные сеттеры, которые начинались с С# 2.

Например, класс счета позволяет пользователю добавлять или удалять элементы из свойства Items, но он не позволяет пользователю изменять ссылку на Items (то есть пользователь не может назначить свойство Items экземпляру объекта списка элементов).


public class Item
{
  public string item_code;
  public int qty;

  public Item(string i, int q)
  {
    this.item_code = i;
    this.qty = q;
  }
}

public class Invoice
{
  public List Items { get; private set; }

  public Invoice()
  {
    this.Items = new List();
  }
}

public class TestInvoice
{
  public void Test()
  {
    Invoice inv = new Invoice();
    inv.Items.Add(new Item("apple", 10));

    List my_items = new List();
    my_items.Add(new Item("apple", 10));

    inv.Items = my_items;   // compilation error here.
  }
}

Ответ 6

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

В таком случае вы можете либо создать метод для расчета

private void Calculate(int value)
{
 //...
}

Или вы можете сделать это, используя

public int MyProperty {get; private set;}

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

Кроме этого, даже если вы скажете, что вы сопоставляете свойство с переменной. В таком случае внутри вашего кода вы хотите написать вот так:

public int myprop;
public int MyProperty {get { return myprop;}}

... ...

this.myprop = 30;

... ...
if(this.MyProperty > 5)
   this.myprop = 40;

Вышеприведенный код выглядит ужасно, поскольку программисту всегда нужно осторожно использовать MyProperty для Get и myprop для Set.

Повторите попытку для консистенции, вы можете использовать частный сеттер, который заставляет Propoerty читать только снаружи, в то время как вы можете использовать его сеттер внутри вашего кода.

Ответ 7

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

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

Эти случаи, хотя в основном, ограничены классами, которые в основном являются "обычными старыми данными". Они также не очень интересны в этом отношении, настолько о них достаточно.

В других случаях на других языках у вас есть метод getter и setter, что-то вроде int getId() для получения значения и void setId(int val) для его обновления.

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

(На самом деле, из-за того, как работает отражение, и таких случаев, как DataBinder.Eval, может быть удобно иметь свойство, даже если поле будет работать нормально, но это другое дело).

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

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

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

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

  • Класс неизменен извне, потому что ни один из публичных членов ничего не меняет, но не гарантирует использование readonly, чтобы не меняться изнутри.

  • Класс неизменен, как видно извне, хотя некоторое состояние изменяется как деталь реализации. Например. поле может быть замечено, и, следовательно, извне попытка получить его просто получает одно и то же значение, первая такая попытка фактически вычисляет его, а затем сохраняет его для извлечения при последующих попытках.

Ответ 8

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

Ответ 9

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

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

Частные сеттеры стали более часто использоваться со стенографией свойств, которая была введена в С# 3. В С# 2 установщик часто просто был опущен, а личные данные были доступны непосредственно при установке.

Это свойство:

public int Size { get; private set; }

совпадает с:

private int _size;
public int Size {
  get { return _size; }
  private set { _size = value; }
}

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

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

Ответ 10

Я не понимаю необходимости иметь частные сеттеры, которые начинались с С# 2.

Пример использования примера:

У меня есть экземпляр объекта приложения 'UserInfo', который содержит свойство SessionTokenIDV1, которое я не хочу показывать пользователям моего класса.

Мне также нужна возможность установить это значение из моего класса.

Мое решение состояло в том, чтобы инкапсулировать свойство, как показано на рисунке, и сделать setter частным, чтобы я мог установить значение токена сеанса, не позволяя экземпляру кода также установить его (или даже увидеть его в моем случае)

public class UserInfo
{
   public String SessionTokenIDV1 { get; set; }

}


public class Example
{
  // Private vars
  private UserInfo _userInfo = new UserInfo();

  public string SessionValidV1
  {
    get { return ((_userInfo.SessionTokenIDV1 != null) && (_userInfo.SessionTokenIDV1.Length > 0)) ? "set" : "unset"; }
    private set { _userInfo.SessionTokenIDV1 = value; }
  }
}

Изменить: Исправлен тег кода Изменить: в примере были исправлены ошибки

Ответ 11

Вам нужен частный сеттер, если вы хотите поддержать следующий сценарий (не только для этого, но это должно указывать на одну вескую причину): У вас есть свойство, которое только для чтения в вашем классе, то есть только сам класс может изменить его, но он может изменить его после создания экземпляра. Для привязок вам нужно будет запустить событие PropertyChanged, предпочтительнее это должно быть сделано в (private) устройстве настройки свойств. Фактически, вы можете просто запустить событие PropertyChanged из другого места в классе, но использование частного сеттера для этого - "хорошее гражданство", поскольку вы не распространяете триггеры изменения свойств по всему классу, но сохраняете его на где он принадлежит.