views:

568

answers:

3

This seems to go against every design guideline. A static method that accepts a single argument of type T should usually just be a member method.

It's so bizzare I actually had to post a StackOverflow question to understand IsUpper exists (as it didn't show up in auto-completion)

Edit

I understand my earlier statement needs a little explaining. An example of a good design is String.ToLower(). Instead of it being prototyped as static void ToLower(String foo), it is a member method. It's pretty obvious (to me at least) that the same should hold for char.IsLower().

+3  A: 

See also this question.

The short version - The initial IDE had trouble coming up with intellisense when invoked from a string literal (and I'm assuming char literals too). So the designers made the methods static to get around this problem.

REEDIT: I had a little rant here about the .NET designers bowing to pressure from IDE designers. But having seen Pop's answer to this question I'm less sure about this now.

EDIT2: Tim in the comments asked if we knew this to be true, or is it just a guess. I couldn't find an exact reference to this issue but I found an article from 2002 talking about an intellisense bug in a string literal. It's about halfway down this page.

Cameron MacFarland
that's a big assumption. Do we actually know? Can we confirm this, or is it just supposition?
Tim
This explanation makes so much more sense than Tim's.
Constantin
Methods on String class and methods on stuctures/primiteves don't have anything in common. This is not the reason. The reason is thread safety. Making a method static is a easy way to make it thread safe as it recieves a copy of the struct.
Pop Catalin
@Pop the only thing they have in common is the language defines literals for them, which the IDE was having trouble with. In that sense string and chars (and ints, floats, decimals etc.) are the same.
Cameron MacFarland
There are many more subtle differences, structs are stack allocated, strings area heap allocated, a struct can be modified in place (by overriding the memory location where it resides) a string cannot.
Pop Catalin
instance methods on strings receive a this reference, that can't change. Instance methods on primitives and structures recieve a pointer to the struct, and that pointer points to volatile memory.
Pop Catalin
I recant on this point as well. It makes sense also. This could very well be one of the reasons it was made static.
Tim
+2  A: 

In my point of view, it does make sense.

There are many static methods which accept single argument. It would not be so nice to calculate a square root using something like this:

double d = 100.0;
Console.WriteLine("Square root of d is " + d.Sqrt());

This would decrease "Cohesion" in term of OO design which is not a good practice. It will be more nice to separate this responsibility to the Math class.

double d = 100.0;
Console.WriteLine("Square root of d is " + Math.Sqrt(d));
m3rLinEz
+5  A: 

Instance methods on structures are not thread safe. Static methods on the other hand are.

Static methods receive a copy of the structure, instance methods a managed pointer. Accessing data through a pointer is not a tread safe operation and can easily lead to race conditions.

That's why most methods on structures/primitives are static and not instance.

Se here a similar question.

Why IsNan is a static method on the Double class instead of an instance property ?

Pop Catalin
That makes no difference in this case. IsLower does not modify the value it operates on.
Daniel Earwicker
No, but it uses the value to determine something (in this case, case). If IsLower wasn't thread safe then multithreaded code could cause IsLower to return the wrong answer.
Cameron MacFarland
IsLower doesn't but someone might modify it from another thread, and since a instance method accesses the values thought a pointer, it migth read a value at first then another on second read. Follow my link it has a example showing that instance methods are not thread safe.
Pop Catalin
I put a comment on that answer - I don't think that proves instance methods on immutable value types are not threadsafe. It proves that if a variable containing an immutable valuetype is shared between threads, they can each assign to it. This would be bad for statics as much as instance methods.
Daniel Earwicker
Check the example again, an instance method reads the value twice and gets different values of it. A static method would always get the same value because it received a copy which can't be modified concurrently.
Pop Catalin
`char` is immutable, so thread safety not an issue.
Jay Bazuzi
Yes but what if the value was modifed _during_ the copy? For a non-trivial struct that's possible. And for ToLower, it only reads the value once so it wouldn't make any difference.
Daniel Earwicker
@Jay Bazuzi: if you follow the link, you'll see an example of how not even immutable structures can have thread safe instance methods.If a structure can be copied over (even if immutable) and is accessed throug a pointer (like a instance method does) then its' not thread safe.
Pop Catalin
@Earwicker if the value is modified during the copy then the race condition is outside the method, not inside it. Race conditions inside framework methods can have various ramifications like security breaches and undefined runtime behavior. Races in you code can only lead to bugs.
Pop Catalin
That doesn't follow - a screwed up value during entry to a method will leave that method looking at a randomly screwed up value. This is no better. The real problem is accidentally sharing a storage location between threads without locking around it properly.
Daniel Earwicker
@Earwicker: as static method doesn't replace proper synchronization, but has the benefit that it can safely assume that the value that was passed it won't change from entry point to exit. I never said that static methods replace synchronization, just that they are guarded from race conditions.
Pop Catalin
What I mean is that no race conditions can affect the data they work on, from the moment the values was passed to them.
Pop Catalin
I can agree with that as long as it's qualified: as long as copying the value type is atomic on the machine architecture. So for compound value types it still isn't safe, because the value may be modified during the copy operation as the method is entered, leaving the method with a corrupted value.
Daniel Earwicker
For a primitive value small enough to be atomically copyable, it's okay, but the result of the call will still be unpredictable, as it will randomly depend on whether the value was modified before or after the call began.
Daniel Earwicker
Also, an instance method on a value type can exactly mimic the behaviour of a static by simply making a copy of 'this' at the start. Then it behaves just like a static method. So it isn't necessary to switch to statics anyway. Put all this together, and I can't see what the concern is.
Daniel Earwicker
@Earwicker: When the instance method copies the value, can you guarantee the value it's copying is the value before or after the value changed in another thread?
Cameron MacFarland
No - and exactly the same is true when the static method copies the value.
Daniel Earwicker