views:

328

answers:

5

In C#, what is the purpose of marking a class static?

If I have a class that has only static methods, I can mark the class static or not. Why would I want to mark the class static? Would I ever NOT want to mark a class static, if all the methods are static, and if I plan to never add a non-static method?

I looked around and saw some similar questions, but none that were just like this.

+5  A: 

If you would like to write extension methods, you have to use a static class. Otherwise it is to show the class will never have any instance data.

Yuriy Faktorovich
+17  A: 

Marking a class as static is a declarative statement that you only intend for this type to have static and const members. This is enforced by the compiler and prevents you from accidentally adding an instance method to the type.

Other advantages

  • Extension methods can only be defined in static classes
  • Prevents users from creating an instance of the class
  • Prevents use of the type as a generic argument (thanks Eric!)
JaredPar
It also prevents consumers from creating an instance of the class. Prior to the introduction of static classes, you had to create a private no-argument constructor to enforce this.
Joel Mueller
@Joel, thanks updated with this
JaredPar
Incidentally, making a class static also prevents use of the type as a generic type argument on a generic class, struct, interface, delegate or method. (What would you do with such a type as a generic type argument? You can't create it, so no variable of that type would ever be non-null. You can't call static methods via a type parameter. It would be completely useless, so we don't allow it.)
Eric Lippert
It's also not possible to derive from it (at least not that I know of, maybe you can write your own IL that does or something), which I guess is rather obvious :)
Skurmedel
@Eric, interesting I didn't know about the generic argument prevention
JaredPar
@Skurmedel: A static class is actually implemented by making a class whose metadata is marked as both "sealed" and "abstract". So no, you cannot derive from it even using IL tricks, because it is sealed.
Eric Lippert
I wish that interfaces were implicitly `static` types, so they could contain `static` members.
Jay Bazuzi
+1  A: 

You mark a class static if you want to force it to contain only static methods, a typical helper class. If you put an instance method the compiler will complain - this is good. In version 1 of the .NET framework there was a class, don't remember which one, that was meant to ship with only static methods. Accidentally one of those methods did not get the static modifier. Because this feature did not exist at the time the bug was spotted very late, after shipping. They did make the constructor private and as such the method could not be used.

smink
+3  A: 

It is a convention specific to the C# language, the CLR has no notion of static classes. It ensures that you cannot accidentally add an instance member in the class, cannot inherit the class and client code cannot accidentally create an instance of the class. The underlying TypeAttributes for the class are Abstract and Sealed. Abstract ensures that the new operator can't work, Sealed ensures that you can't inherit from the class.

Also by convention, extension methods must be static members of a static class. VB.NET does it differently, it requires the [Extension] attribute.

Using static classes in your code is not necessary, but it is useful. Their contract is very descriptive, it makes your code easier to understand. But be careful not to use them as a vehicle to write procedural code instead of OOP code.

Hans Passant
+1 for implementation details and mentioning of overuse to write procedural code.
Si
+6  A: 

Marking a class as static gets you two important things.

  • Compiler verification that you only put static members in a class.

  • An obvious statement to readers of your code that this class is only a container for static members.

The feature was invented in response to a bug in NDP v1.0, where a un-callable non-static member was included in the System.Environment class.

Jay Bazuzi
Aside: I've wished for a similar `readonly` modifier on types, which requires all fields to be marked `readonly` and to be of types that are marked `readonly`. The NDP would have to be annotated accordingly, especially the primitive types. Unfortunately there's a large body of code written with mutable idioms (e.g. `List<T>`, so it's too late.
Jay Bazuzi