Why is DateTime.Now a property and not a method?
After reading this blog entry : http://wekeroad.com/post/4069048840/when-should-a-method-be-a-property,
I'm wondering why Microsoft choose in C# :
DateTime aDt = DateTime.Now;
instead o开发者_运维百科f
DateTime aDt = DateTime.Now();
- Best practices say : Use a method when calling the member twice in succession produces different results
- And
DateTime.Now
is perfect example of non-determistic method/property.
Do you know if there any reason for that design ?
Or if it's just a small mistake ?I believe in CLR via C#, Jeffrey Richter mentions that DateTime.Now is a mistake.
The System.DateTime class has a readonly Now property that returns the current date and time. Each time you query this property, it will return a different value. This is a mistake, and Microsoft wishes that they could fix the class by making Now a method instead of a property.
CLR via C# 3rd Edition - Page 243
It actually is deterministic; it's output is not random, but is based on something quite predictable.
The 'current time' changes all the time; so to be relatively "the same" with each call, that value must change so that every time it's called, it's returning the current time.
EDIT:
This just occurred to me: Of course, two subsequent calls to a property getter can return different results, if something changed the property value in the interim. Properties are not supposed to be Constants
.
So, that's what happening (conceptually) with DateTime.Now
; its value is being changed between subsequent calls to it.
According to MSDN you should use a property when something is a logical data member of the object:
http://msdn.microsoft.com/en-us/library/bzwdh01d%28VS.71%29.aspx#cpconpropertyusageguidelinesanchor1
The go on to list out the cases where a method would be more appropriate. What is ironic is that one of the rules for a method is to use it when successive calls may return different results and of course Now certainly meets that criteria.
Personally I think this was done to eliminate the needs for the extra (), but I have found the absence of () confusing; it took me a little while to shift from the old approach in VB/VBA.
Guidelines are just that, not hard and fast rules.
Those guidelines are intended for stateful objects, and in reality are trying to say that properties should not mutate an object. DateTime.Now is a static property, so calling it does not mutate an object. It's also merely reflecting the natural state of time, not changing anything. It is simply observing a constantly changing timer.
So the point is, don't create properties that change the state of the object. Do create properties that merely observe the state of the object (even if the state changes externally).
As another example, let's look at the length of a string. This is a property, but the length of the string can change from invocation to invocation if something else changes the string externally. That's basically what is going on, the timer is being changed externally, Now just reflects its current state just as string.Length or any other such property.
In deciding "method versus property", a suggested test is "will successive calls return different results". I would suggest that a better test is the similar, but not identical question, "will calling the routine affect the outcome of future calls to the same or different routines?" In most cases, the answers to both the questions will be the same, since by far the most common reason that later calls to a routine will yield different results from the former one would be that the former one caused the later call to return a different result than it otherwise would have.
In the case of DateTime.Now, the only way in which one call would affect the value returned by another would be if the execution time taken by the first call caused the second call to occur measurably later than it otherwise would have. While a pedant might consider the passage of time to be a state-altering side effect of the first call, I would suggest that there are many properties which take longer to execute than DateTime.Now, and thus a call to any of those would have a greater likelihood of changing the value returned by a subsequent DateTime.Now call.
Note that if the "get time" routine were a virtual class member rather than being a static member, that would shift the balance in favor of making it a method; while the "expected" implementation would not affect the state of any object, it would be likely--or at least plausible--that some implementations might have side-effects. For example, calling Now on a RemoteTimeServer object might attempt to get the time from a remote server, and such attempt might have considerable side-effects on the rest of the system (e.g. by causing one or more machines to cache DNS/IP routing information, such that the next attempt to access the same server will complete 100ms faster).
Since there are no brightline rules on when to use a method and a property, DateTime.Now is truly just reading an exposed property of the state of the server, it may be constantly changing, but DateTime.Now never effects the state of any property, object or what not, so it is a property in the Framework.
精彩评论