Почему DateTime.Now свойство, а не метод?

После прочтения этой записи в блоге: http://wekeroad.com/post/4069048840/when-should-a-method-be-a-property,

Мне интересно, почему Microsoft выбрала С#:

DateTime aDt = DateTime.Now;

вместо

DateTime aDt = DateTime.Now();
  • Лучшие практики говорят: используйте метод при вызове члена дважды подряд, вы получите разные результаты.
  • И DateTime.Now - прекрасный пример недетерминированного метода/свойства.

Знаете ли вы, есть ли причина для этого дизайна?
Или если это всего лишь небольшая ошибка?

Ответ 1

Я верю в CLR через С#, Джеффри Рихтер упоминает, что DateTime.Now является ошибкой.

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

CLR через С# 3rd Edition - Страница 243

Ответ 2

Фактически это детерминировано; он выводится не случайно, а основан на чем-то вполне предсказуемом.

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

EDIT:

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

Итак, что происходит (концептуально) с DateTime.Now; его значение изменяется между последующими вызовами к нему.

Ответ 3

Руководства - это просто, а не жесткие и быстрые правила.

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

Итак, дело в том, что не создавайте свойства, которые изменяют состояние объекта. Создавайте свойства, которые просто наблюдают за состоянием объекта (даже если состояние изменяется извне).

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

Ответ 4

В соответствии с MSDN вы должны использовать свойство, когда что-то является логическим элементом данных объекта:

http://msdn.microsoft.com/en-us/library/bzwdh01d%28VS.71%29.aspx#cpconpropertyusageguidelinesanchor1

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

Лично я думаю, что это было сделано для устранения потребностей в дополнительном(), но я обнаружил отсутствие() запутанности; мне потребовалось немного времени, чтобы перейти от старого подхода в VB/VBA.

Ответ 5

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

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

Обратите внимание, что если подпрограмма "получить время" была членом виртуального класса, а не статическим членом, это изменило бы баланс в пользу создания метода; в то время как "ожидаемая" реализация не повлияет на состояние какого-либо объекта, вероятно, или, по крайней мере, правдоподобно, что некоторые реализации могут иметь побочные эффекты. Например, вызов Now на объекте RemoteTimeServer может попытаться получить время с удаленного сервера, и такая попытка может иметь значительные побочные эффекты для остальной части системы (например, заставляя одну или несколько компьютеров кэшировать информацию о маршрутизации DNS/IP, так что следующая попытка доступа к одному и тому же серверу будет быстрее на 100 мс).

Ответ 6

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