c# - поля - экземпляр класса




Является ли создание объекта в геттерах плохой практикой? (10)

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

У меня был класс с

private Collection<int> moo;

public Collection<int> Moo
{
  get 
  {
    if (this.moo == null) this.moo = new Collection<int>();
    return this.moo;
  }
}

Тогда где-то еще в классе появился публичный метод, который ссылался

this.moo.Add(baa);

без проверки он был создан.

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

Некоторое время я должен признать, что думал, что сойду с ума. Отладчик - без ошибок. Ошибка выполнения. Много царапин на голове позже я заметил ошибку и понял, что отладчик Visual Studio создавал экземпляр коллекции, поскольку он отображал общедоступные свойства этого класса.

Давайте создадим объект, созданный в getter следующим образом:

public class Class1
{
       public string Id { get; set; }
       public string Oz { get; set; }
       public string Poznamka { get; set; }

       public Object object
       {
             get
             {
                  // maybe some more code
                  return new Object { Id = Id, poznamla = Poznamka, Oz = OZ };
             }
        }
 }

Или мне лучше создать метод, который будет создавать и возвращать объект?


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


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

т.е. в то время как в тестовых случаях вы не проводите проверку некоторых конкретных предметов.

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


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

Однако это обычно не требуется для свойств (т. Е. Геттеров и сеттеров), и поэтому считается плохой практикой.


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

  1. Избегайте возврата различных значений из свойства getter. Если вы вызываете несколько раз подряд, метод свойств может возвращать другое значение каждый раз; поле возвращает одно и то же значение каждый раз.

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

  3. Учтите, что свойство не может быть передано методу out или ref; поле может.

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

  5. Избегайте бросать исключения из геттеров.

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

  7. Избегайте наблюдаемых побочных эффектов.

  8. Разрешить настройку свойств в любом порядке, даже если это приводит к временному недопустимому состоянию объектов.

источники

« CLR через C # », Джеффри Рихтер. Глава 9. Определение свойств интеллектуально

« Руководство по разработке рамок » 2-е издание, Брэд Абрамс, Кшиштоф Квалина, Глава 5.2.


Свойство - это просто удобный способ выражения вычисленного поля.

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

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

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

Там также есть свойство свойств, где вы можете так легко и невинно обращаться к собственности несколько раз и в конечном итоге работать с тем же кодом (который, надеюсь, не медленный!).


Согласно мне, если что-то является «свойством», геттер должен вернуть вам свойство (в основном, уже существующее), относящееся к объекту.

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

Вместо этого я бы использовал метод, похожий на GetMyObject (). Особенно, если есть «действие», я думаю, что в большинстве случаев лучше иметь метод, чем имя свойства.

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


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


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

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


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

при чтении дважды из поля или свойства вы ожидаете две вещи:

  • нет никакого влияния на поведение объекта (внешнего)
  • вы получаете одинаковые результаты

У меня нет реального знания о C #, но я надеюсь, что следующее мое мнение ясно. давайте начнем вот так:

Object o1 = myInst.object;
Object o2 = myInst.object;
o1.poznamka = "some note";

в случае поля будут выполняться следующие условия:

o1 == o2;
o2.poznamka == "some note";

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

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





getter