tags:

views:

300

answers:

9

I need to explain myself why I do not use static methods/propertis. For example,

String s=String.Empty;

is this property (belongs to .Net framework) wrong? is should be like?

String s= new EmptySting();

or

IEmptyStringFactory factory=new EmptyStringFactory();

String s= factory.Create();
+7  A: 

I think the worst thing about using statics is that you can end up with tight coupling between classes. See the ASP.NET before System.Web.Abstractions came out. This makes your classes harder to test and, possibly, more prone to bugs causing system-wide issues.

Will
+7  A: 

Why would you want to create a new object every time you want to use the empty string? Basically the empty string is a singleton object.

As Will says, statics can certainly be problematic when it comes to testing, but that doesn't mean you should use statics everywhere.

(Personally I prefer to use "" instead of string.Empty, but that's a discussion which has been done to death elsewhere.)

Jon Skeet
OK. Sorry, but... umm... huh? "that doesn't mean you should statics everywhere" seems to be missing a verb in there. Could you clarify your answer. Not to poke too hard, but maybe you should add a bit about static properties in general, not just String.Empty. This seems a bit of a incomplete answer and almost deserves the down-vote -- not that it would hurt your rep, but just to keep you honest :)
Erich Mirabal
Okay, corrected the typo... will think about expanding the answer...
Jon Skeet
+1  A: 

Generally, it is a bad idea to create a new empty string - this creates extra objects on the heap, so extra work for the garbage collector. You should always use String.Empty or "" when you want the empty string as those are references to existing objects.

thecoop
The compiler could easily string-pool this. I'm guessing it does.
But if you create a new string using String() then (IIRC) you will need to explicitly intern it using String.Intern to get the 'shared' version used by String.Empty and ""
thecoop
+2  A: 

The semantics of your three different examples are very different. I'll try to break it down as I do it in practice.


String s=String.Empty;

This is a singleton. You would use this when you want to ensure that there's only ever one of something. In this case, since a string is immutable, there only ever needs to be one "empty" string. Don't overuse singletons, because they're hard to test. When they make sense, though, they're very powerful.


String s= new EmptySting();

This is your standard constructor. You should use this whenever possible. Refactor to the singleton pattern only when the case for a singleton is overwhelming. In the case of string.Empty, it very much makes sense to use singleton because the string's state cannot be changed by referring classes.


IEmptyStringFactory factory=new EmptyStringFactory();
String s= factory.Create();

Instance factories and static factories, like singletons, should be used sparingly. Mostly, they should be used when the construction of a class is complex and relies on multiple steps, and possibly state.

If the construction of an object relies on state that might not be known by the caller, then you should use instance factories (like in your example). When the construction is complex, but the caller knows the conditions that would affect construction, then you should use a static factory (such as StringFactory.CreateEmpty() or StringFactory.Create("foo"). In the case of a string, however, the construction is simple enough that using a factory would smell of a solution looking for a problem.

Michael Meadows
I would never advocate the use of a singleton except in a performance optimizing scenario. Software design is wrought with requirement changes. What one thinks you'll only need one of right now will soon turn in to two or more when requirements change. Refactoring code from a singleton pattern to a normal instance pattern is a *significant* change and gets worse as the project gets bigger.
@clemahieu, I believe that the singleton is the single worst pattern (considering how badly it's done often and how often it's done badly). However, "never" is a little dogmatic. It isn't necessary a preoptimization to use singletons in some scenarios. One of these is the "Empty" or "Null Object" pattern. Another is when you must ensure that there is one and only one instance of a class available. I think I agree with the sense of your argument, but never is too powerful of a word.
Michael Meadows
+2  A: 

Well, in the case of String.Empty it is more of a constant (kind of like Math.PI or Math.E) and is defined for that type. Creating a sub-class for one specific value is typically bad.

On to your other (main) question as to how they are "inconvenient:"

I've only found static properties and methods to be inconvenient when they are abused to create a more functional solution instead of the object-oriented approach that is meant with C#.

Most of my static members are either constants like above or factory-like methods (like Int.TryParse).

If the class has a lot of static properties or methods that are used to define the "object" that is represented by the class, I would say that is typically bad design.

One major thing that does bother me with the static methods/properties is that you sometimes they are too tied to one way of doing something without providing an easy way to create an instance the provides with easy overrides to the behavior. For example, imagine that you want to do your mathematical computations in degrees instead of radians. Since Math is all static, you can't do that and instead have to convert each time. If Math were instance-based, you could create a new Math object that defaulted to radians or degrees as you wished and could still have a static property for the typical behaviors.

For example, I wish I could say this:

Math mD = new Math(AngleMode.Degrees); // ooooh, use one with degrees instead
double x = mD.Sin(angleInDegrees);

but instead I have to write this:

double x = Math.Sin(angleInDegrees * Math.PI / 180);

(of course, you can write extension methods and constants for the conversions, but you get my point).

This may not be the best example, but I hope it conveys the problem of not being able to use the methods with variations on the default. It creates a functional construct and breaks with the usual object-oriented approach.

(As a side note, in this example, I would have a static property for each mode. That in my eyes would be a decent use of the static properties).

Erich Mirabal
I think you might mean "more procedural solution" instead of "more functional solution." Static methods and properties are similar to the "methods acting on structures" practice of the procedural programming paradigm. The functional paradigm relies on match operations on sets.
Michael Meadows
Yes. I meant "function-based" as in procedures. Not "functional programming" as in F#.
Erich Mirabal
+1  A: 

In general, the purpose of a static is to make sure that there is ever only one instance of the static "thing" in your program.

  • Static fields maintain the same value throughout all instances of a type
  • Static methods and properties do not need an instance in order to be invoked
  • Static types may only contain static methods/properties/fields

Statics are useful when you know that the "thing" you are creating will never change through the lifetime of the program. In your example, System.String defines a private static field to store the empty string, which is allocated only once, and exposed through a static property.

As mentioned, there are testability issues with statics. For example, it is hard to mock static types since they can't be instantiated or derived from. It is also hard to introduce mocks into some static methods since the fields they use must also be static. (You can use a static setter property to get around this issue, but I personally try to avoid this as it usually breaks encapsulation).

For the most part, use of statics is o.k. You need to decide when to make the trade-off of using static and instance entities based on the complexity of your program.

Steve Guidi
+1, this didn't deserve a downvote. It seems that apparently this concept of "when to use static members/classes" is one of those flame generating issues where people tend to attack anyone who even slightly disagrees with them. I don't entirely agree with your degree with the "OKness" of using statics, but there's nothing incorrect about what you're saying.
Michael Meadows
+1  A: 

In a purist OO approach, static methods break the OO paradigm because you're attaching actual data to the definition of data. A class is a definition of a set of objects that conform to semantics. Just like there are mathematical sets that contain one or zero elements, there can be classes that contain only one or zero possible states.

The way of sharing a common object and allowing multiple actors on its state is to pass a reference.

The main problem with static methods comes from, what if in the future you want two of them? We're writing computer programs, one would assume that if we can make one of something, we should be able to make two very simply, with statics this isn't the case. To change something from a static state to a normal instance state is a complete rewrite of the class in question.

I might assume I want to only ever use one SqlConnection pool, but now what if I want a high priority pool and a low priority pool. If the connection pool was instanced instead of static the solution would be simple, instead I have to couple pooling with connection instantiation. I better hope the library writer had forsight or else I have to reimplement the pooling.

Edit: Static methods in single inheritance languages are a hack to provide reuse of code. Normally if there are methods one wanted to share common code between classes you could pull it in through multiple inheritance or a mixin. Single inheritance languages force you to call static methods; there's no way to use multiple abstract classes with state.

+1  A: 

There are draw backs to using statics such as:

  1. Statics dont allow extension methods.
  2. Static constructor is called automatically to initialize the class before the first instance is created (depending on the static class being called of course)
  3. Static class data lives throughout the lifespan of the execution scope, this wastes memory.

Reasons to use static methods

  1. Statics are good for helper methods, as you dont want to create a local copy of a non-static class, just to calla single helper method.
  2. Eeerm, static classes make the singleton pattern possible.
Neil
A: 

From a scenario-driven design, the criteria for choosing statics vs. instance methods should be: if a method can be called without an instance of a class to be created, make it static. Else, make it an instance method. First option makes the call a once line process, and avoid .ctor calls.

Another useful criteria here is whether responsabilities are in the right place. For ex. you got an Account class. Say you need functionality for currency conversion e.g. from dollars to euros. Do you make that a member of the Account class? account.ConvertTo(Currency.Euro)? Or do you create a different class that encapsulates that responsibility? CurrencyConverter.Convert(account, Currency.Euro)? To me, the latter is better in the sense that encapsulates responsibilities on a different class, while in the former I would be spreading currency conversion knowledge across different accounts.

Ariel