Sunday, June 15, 2008

Best practices for statics

1. .NET also supports type constructors also known as static constructors, class constructors or type initializers. A type's constructor is guaranteed to run before any instance of the type is created and before any static field or method of the type is referenced.

a. Implicit static constructor

class AType {
static int x = 5;
}


When this code is built, the compiler automatically generates a type constructor for AType. This constructor is responsible for initializing the static field x to the value 5.

b. Explicit static constructor



class AType {
static int x;

static AType() {
x = 5;
}
}


When you run FxCop, b would give a warning "Do not declare explicit static constructors." The rule description tells you that an explicit static constructor results in code that performs worse. The recommendation from FxCop is to initialize static fields where they are declared. The reason for this is that implicit static constructors can be run at anytime the runtime where as if an explicit static constructor is defined, the runtime must run the type constructor at a precise time—just before the first access to static or instance fields and methods of the type and the precise timing restrictions lead to the performance drop hinted at by FxCop. The checks that the runtime performs in order to run the type initializer at a precise time adds overhead.

2. Exceptions in static constructors

a. The runtime will stop any exceptions trying to leave a type constructor and wrap the exception inside of a new TypeInitializationException object. The original exception thrown inside the type constructor is then available from the InnerException property of the TypeInitializationException object. One reason this special behavior might occur is that the second time you try to access a static property of the type, the runtime does not try to invoke the type constructor again, but throws the same exception observed in the first iteration. The runtime does not give a type constructor a second chance. The same rules hold true if the exception is thrown from a static field initializer. As you saw earlier, the code for a static field initializer executes inside an implicit type constructor.

b. A TypeInitializationException can be a fatal error in an application since it renders a type useless. You should plan to catch any exceptions inside of a type constructor if there is any possibility of recovering from the error, and you should allow an application to terminate if the error cannot be reconciled.

c. When an exception is thrown, the runtime will begin to look for the nearest catch clause whose filters specify that it can handle the exception.

3. The rule of thumb here is to avoid touching the static members of another type from within a type constructor. Although the chances of seeing the previous scenario are slim, the effects would be difficult to debug and track down since there are few diagnostics available.

4. Static members are not inherited. Though static members are not inherited, they can still be accessed with derived class type.

5. If you have a class with only static members, you would not want to
a. Allow it to get derived (use sealed keyword)
b. Allow it to be instantiated (private default constructor)

A solution to both of this is the static classes.

The new syntax allows the compiler to enforce a number of new rules.

a. You cannot declare a variable of type Static1 because it is marked as a static class.
b. You also cannot derive from Static1, or add any non-static members to the class.
c. Note also that it's an error to derive a static class from any class other than object.

6. You should also remember that static classes that preserve state between method calls should be made thread safe by default. Making a class thread safe requires additional care during the implementation and testing of the class. Before going down this road, ask yourself if the extra overhead is absolutely necessary.



7. The .NET Framework guarantees thread safety on static type initialization.



class Singleton{
public static readonly Singleton Instance = new Singleton();
}

No comments: