Defining Static Members

At times, you may wish to share a field value across all instances of your class.  The typical (non-static) field is
allocated per object. One object’s value is distinct from another object’s value. These are called
instance fields.   
To define a field that is allocated once and shared between all instances, use the static modifier.  


Consider a class that represents a savings account:
       •        The account balance is an instance field because each savings account object needs a distinct balance.
       •        On the other hand, the interest rate is a static field. If the Fed changes the rate, the banker wants it to
                 
be reflected in all savings account instances.


class SavingsAccount
{
  private double mBalance;

  private static double mInterestRate = 0.04;

  
  public SavingsAccount(double balance)
  { mBalance = balance; }

  public double GetEarnedInterest()
  {
     return mBalance * mInterestRate;
  }
  
  public double InterestRate
  {
     get{ return mInterestRate; }
     set{ mInterestRate = value; }
  }
}


Look at what happens when the following code executes.


static void Main(string[] args)
{
  SavingsAccount s1 = new SavingsAccount(50);
  SavingsAccount s2 = new SavingsAccount(100);
  SavingsAccount s3 = new SavingsAccount(10000.75);
}





















Now look at another code example:


static void Main(string[] args)
{
  SavingsAccount s1 = new SavingsAccount(50);
  SavingsAccount s2 = new SavingsAccount(100);

  // Changing the interest rate.

  s2.InterestRate = 0.08;
  Console.WriteLine("Current rate is {0}", s1.InterestRate);

  // Create another account. Does the rate get set back to 0.04?

  SavingsAccount s3 = new SavingsAccount(10000.75);
  Console.WriteLine("Current rate is {0}", s1.InterestRate);
}



The output demonstrates that the runtime only initializes the static field once, not each time an instance is
created.  The runtime guarantees that a static field will be initialized sometime before it is first accessed.













You can also implement custom static initialization logic by providing a static constructor within the class.          
A static constructor must not have any access modifiers and cannot take any parameters.  The runtime invokes
the static constructor when it creates an instance of the class or before accessing a static member.  The static
constructor executes before any instance constructors.


class SavingsAccount
{
  private double mBalance;
  private static double mInterestRate; // Set to default value.

  // Static constructor! Note: No access modifier, no params.

  static SavingsAccount()
  {

     // Implement custom static initialization logic.

     Console.WriteLine("In static constructor!");
     mInterestRate = 0.04;
  }
  
  public SavingsAccount(double balance)
  {
     Console.WriteLine("In instance constructor!");
     mBalance = balance;
  }
...
}


For example, here’s some consuming code and the output:


static void Main(string[] args)
{
  SavingsAccount s1 = new SavingsAccount(50);
  Console.WriteLine("Current rate is {0}", s1.InterestRate);
}















In addition to static fields, you can also define static methods and properties.  A static method or property can
only access other static members.   For example, make the InterestRate property static:


class SavingsAccount
{
  public static double InterestRate
  {
     get{ return mInterestRate; }
     set{ mInterestRate = value; }
  }
...
}


Consumers access non-private static members using the class name instead of an object reference.


static void Main(string[] args)
{

 // Ok! Static members can only be accessed via the class name.

 SavingsAccount.InterestRate = .08; // <-- static constructor
called                                       
                                    // here.

 SavingsAccount s1 = new SavingsAccount(50);

 // Error! Trying to access static member with object reference!

 s1.InterestRate = .08;
}


Recall that the Main() method must be declared static within a class.  Other than the fact that Main() serves as
the entry point for the application, it behaves just like any other static member of the class.  Consider the
following class definition:


class SavingsAccount
{
  private double mBalance;
  private static double mInterestRate = 0.04;

  public SavingsAccount(double balance)
  { mBalance = balance; }

  public double GetEarnedInterest()
  { return mBalance * mInterestRate; }

  static void Main(string[] args)
  {
     int interest;
     

     // Accessing a static member from a static member. OK!

     mInterestRate = .08;

     // Accessing an instance member from a static member. Error!

     interest = GetEarnedInterest();

     // Construct an object and access the instance member. OK!

     SavingsAccount sa = new SavingsAccount(50);
     interest = sa.GetEarnedInterest();
  }
}


Static Class Definitions

Utility classes (such as the System.Console, System.Math or System.Environment types) are usually designed
to expose all functionality via static members.   Given this, utility types are not intended to be allocated via
‘new’.  Prior to .NET 2.0, utility classes could be configured in one of two manners in order to ensure the end
user cannot allocate an instance:

Redefine the default constructor as private (and provide no other constructors).


class MyUtilClass
{

 private MyUtilClass(){}

...
}


Define the class as an abstract type (to prevent creation).


// More information on the ‘abstract’ keyword after the next lab...
abstract
class MyUtilClass  
{
...
}


While these approaches work, there are a few problems.  First, they are not type safe. The compiler will allow
non-static members to be defined within the utility type.  Second, neither is a very clean solution.   Since .NET
2.0, utility classes can now be marked as static.  Static classes can only contain static members (if not, you
receive a complier error).  Using this approach, there is no need to tweak the default constructor or mark the
type as abstract.


namespace CSharp20Lang
{

 static
class MyUtilClass
 {
   public
static void PrintTime()
   {
     Console.WriteLine(DateTime.Now.TimeOfDay);
   }
 }

 
static class Program
 {
   
static void Main(string[] args)
   {
     MyUtilClass.PrintTime();
   }

   // Compiler error! only static members in a static class!!

   public void InstanceMethod(){}
 }
}


















Defining Static Members
Table of Contents
C# Tutorial | C#.NET Tutorial | Static Members Tutorial

Copyright (c) 2008.  Intertech, Inc. All Rights Reserved.  This information is to be used
exclusively as an online learning aid.  Any attempts to copy, reproduce, or use for training is
strictly prohibited.
Courseware
Training Resources
Tutorials
Services