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

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

Пусть объект, созданный в геттере, выглядит следующим образом:

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Источники

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

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

Ответ 2

Да, это плохая практика.

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

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

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

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

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

Ответ 5

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

Вместо этого используйте класс оболочки или аналогичный.

Ответ 6

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

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

Я бы выбрал метод, похожий на GetMyObject(). Особенно, если есть "действие", я думаю, что в большинстве случаев лучше иметь метод, чем имя свойства.

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

Ответ 7

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

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

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

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

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

Ответ 8

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

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

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

Ответ 9

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

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

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 создавал экземпляр коллекции, поскольку он отображал общедоступные свойства этого класса.

Ответ 10

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

Ответ 11

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

Ответ 12

Это плохая практика. В вашем примере вы должны ожидать один и тот же Object при каждом доступе к свойству Object.

Ответ 14

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

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