Click here to Skip to main content
15,891,633 members
Articles / Programming Languages / C#

Introducing C# 2.0 static classes

Rate me:
Please Sign up or sign in to vote.
3.10/5 (18 votes)
3 Oct 2005CPOL2 min read 99.5K   20   6
A general discussion on C# 2.0 static classes.

Introduction

The use of static classes should not be confused with the common practice in Java to represent an inner class as a nested top-level class in order to conveniently group related classes without creating a new package. Rather, it provides a mechanism to explicitly declare a class as not instantiable. Creating a class that is not intended to be instantiated and which contains only static members has historically been accomplished by declaring it as sealed with a private constructor, as specified in the example below:

C#
public sealed class BluetoothUART
{
    int broadcastBand;
    
    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);

    private BluetoothUART()
    {
    }

    public int BroadCastBand
    {
      get
      {
          return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
          return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

The example above declares a sealed class BluetoothUART with a private constructor and a static property DeviceID. Attempting to instantiate this class will result in a compile time error.

C#
BluetoothUART blu = new BluetoothUART(); //wont work
Console.WriteLine(BluetoothUART.DeviceID);  //works

Using this approach will prevent instantiation and subclassing of the given class, but it neither prevents the use of the class as the type of a variable or parameter, nor does it prevent the class from declaring instance members. The example below illustrates the shortcomings of the above strategy:

C#
public sealed class BluetoothUART
{
    int broadcastBand;

    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);

    private BluetoothUART()
    {
    }

    public int BroadCastBand
    {
      get
      {
        return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
        return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

class Program
{
    static void Main(string[] args)
    {
      BluetoothUART buart = null;
      Console.WriteLine(BluetoothUART.DeviceID);  //works
    }
}

As you can see from the example, although defining BluetoothUART is sealed with a private constructor, it can still be used as the type of the variable buart; a useless exercise since it can only be null, and can still define instance properties, methods, and fields, which will, of course, be inaccessible since no instance will ever exist to access them through. C# 2.0 introduces the concept of static classes as a means to formalize the underlying design pattern and provide much stronger checking of the restrictions that are logically associated with it. The static construct can be utilized to rewrite the BluetoothUART class defined above, as follows:

C#
public static class BluetoothUART
{
    int broadcastBand;
    
    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);
    

    public int BroadCastBand
    {
      get
      {
        return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
        return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

In the example above, the sealed keyword has been replaced with static, and the private constructor has been removed as it is unnecessary. Attempting to build this class will generate a compile time error since the instance field and property have not been removed. This serves as evidence of the tighter restrictions enforced when the class is defined as static rather than sealed with a private constructor. A version of the BluetoothUART class that will compile is given below:

C#
public static class BluetoothUART
{
    static int broadcastBand = 0;
    
    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);
    
    public static int BroadCastBand
    {
      get
      {
        return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
        return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

Given the sample above, you will also find that the consuming class definition defined below will fail to compile.

C#
class Program
{
    static void Main(string[] args)
    {
      BluetoothUART buart = null; //fails to compile
      Console.WriteLine(BluetoothUART.DeviceID);  //works
    }
}

Again, this is due to the stronger restrictions applied to static classes which do not permit instance fields or for types of that class to be used as a variable's type. Likewise, a static class cannot be defined as sealed or abstract, so neither class definition below will compile.

C#
//sealed will not compile
public sealed static class BluetoothUART
{
    static int broadcastBand = 0;

    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);
    
    public static int BroadCastBand
    {
      get
      {
        return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
        Return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

//abstract will not compile
public abstract static class BluetoothUART
{
    static int broadcastBand = 0;

    [DllImport("user32.dll")]
    static extern int DeviceIOControl(string guid);
    
    public static int BroadCastBand
    {
      get
      {
        return this.broadcastBand;
      }
    }

    public static int DeviceID
    {
      get
      {
        return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
      }
    }
}

Another restriction on static classes prevents us from defining parent classes or defining interfaces for it, so the example defined below will also not compile:

C#
public static class BluetoothUART : System.StringComparer
{
   static int broadcastBand = 0;

   [DllImport("user32.dll")]
   static extern int DeviceIOControl(string guid);

   public static int BroadCastBand
   {
       get
       {
          return this.broadcastBand;
       }
   }

   public static int DeviceID
   {
       get
       {
          return DeviceIOControl("49ECA277-65F7-446b-9206-4C09580DDD88");
       }
   }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Hi I'm Edward Moemeka,
For more interesting articles about stuff check out my blog at http://moemeka.blogspot.com
To correspond, email me at edward.moemeka@synertry.com
To support my company, thus help me feed my family, check out our awesome online preview at www.synertry.com. Remember, its in alpha Wink | ;-)

Comments and Discussions

 
GeneralMy vote of 5 Pin
Akhil Mittal20-Mar-13 21:00
professionalAkhil Mittal20-Mar-13 21:00 
GeneralJust what the doctor ordered. Pin
Grahame A19-Sep-08 1:16
Grahame A19-Sep-08 1:16 
Questionhow can u say..? Pin
karthick.n.mca18-Oct-07 3:19
karthick.n.mca18-Oct-07 3:19 
AnswerRe: how can u say..? Pin
Southmountain28-Nov-19 8:14
Southmountain28-Nov-19 8:14 
GeneralThanks Pin
Drew Noakes18-Aug-06 6:04
Drew Noakes18-Aug-06 6:04 
Clear and succinct. You explained this to me in just a few minutes. Many thanks.

Drew Noakes
drewnoakes.com

GeneralRe: Thanks Pin
noange111-May-07 3:11
noange111-May-07 3:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.