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




экземпляр класса (12)

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

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

Давайте создадим объект, созданный в 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 };
             }
        }
 }

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


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

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

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

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

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

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

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

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

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

источники

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

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


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

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


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

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

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

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

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


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

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

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

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



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


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

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


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

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


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


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

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

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