Использование свойств и методов для расчета изменяющихся значений - PullRequest
2 голосов
/ 01 марта 2012

Существует ли соглашение о том, использовать ли свойство для вычисления значения по вызову?Например, если мой класс содержит список целых чисел, и у меня есть свойство Average, среднее значение, возможно, изменится, когда целое число будет добавлено / удалено / изменено из списка, и сделает что-то вроде этого:

    private int? _ave = null;
    public int Average
    {
        get
        {
            if (_ave == null )
            {
                double accum = 0;
                foreach (int i in myList)
                {
                    accum += i;
                }
                _ave = accum / myList.Count;
                return (int)_ave;
            }
            else
            {
                return (int)_ave;
            }
        }
    }

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

Есть ли какие-либо традиционные преимущества / недостатки по сравнению с вызовом метода усреднения?

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

Ответы [ 3 ]

12 голосов
/ 01 марта 2012

Соглашения:

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

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

Относительно вашей конкретной реализации: я был бы гораздо более склонен использовать 64-разрядное целое число в качестве аккумулятора, а не 64-разрядное двойное число; двойной имеет только 53-битную целочисленную точность по сравнению с 64-битной длинной.

3 голосов
/ 01 марта 2012

Рекомендация Microsoft по использованию методов:

Использование метода

  • Если вызов имеет побочные эффекты
  • Если он возвращает разные значения, каждый вызов
  • Если для вызова требуется
  • Если операция требует параметров (кроме индексаторов)

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

В вашем случае ядумаю, что свойство с неявным ленивым вычислением будет хорошим выбором.

2 голосов
/ 01 марта 2012

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

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

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

...