静态构造函数

One novel feature of C# is that it is also possible to write a static no-parameter constructor for a class. Such
a constructor will be executed only once, as opposed to the constructors written so far, which are instance
constructors that are executed whenever an object of that class is created.
class MyClass
{
   static MyClass()

{
      // initialization code
   }
   // rest of class definition
}
One reason for writing a static constructor is if your class has some static fields or properties that need to be
initialized from an external source before the class is first used.
The .NET runtime makes no guarantees about when a static constructor will be executed, so you should
not place any code in it that relies on it being executed at a particular time (for example, when an assembly
is loaded). Nor is it possible to predict in what order static constructors of different classes will execute.
However, what is guaranteed is that the static constructor will run at most once, and that it will be
invoked before your code makes any reference to the class. In C#, the static constructor is usually executed
immediately before the first call to any member of the class.
Notice that the static constructor does not have any access modifiers. It’s never called by any other C# code,
but always by the .NET runtime when the class is loaded, so any access modifier such as public or private
would be meaningless. For this same reason, the static constructor can never take any parameters, and there
can be only one static constructor for a class. It should also be obvious that a static constructor can access
only static members, not instance members, of the class.
Note that it is possible to have a static constructor and a zero-parameter instance constructor defined in
the same class. Although the parameter lists are identical, there is no conflict. That’s because the static
constructor is executed when the class is loaded, but the instance constructor is executed whenever an
instance is created — so there won’t be any confusion about which constructor gets executed when.
Note that if you have more than one class that has a static constructor, the static constructor that will be
executed first is undefined. This means that you should not put any code in a static constructor that depends
on other static constructors having been or not having been executed. However, if any static fields have been
given default values, these will be allocated before the static constructor is called.
The next example illustrates the use of a static constructor and is based on the idea of a program that has
user preferences (which are presumably stored in some configuration file). To keep things simple, we’ll
assume just one user preference — a quantity called BackColor, which might represent the background
color to be used in an application. And because we don’t want to get into the details of writing code to read
data from an external source here, we’ll make the assumption that the preference is to have a background
color of red on weekdays and green on weekends. All the program will do is display the preference in a
console window — but this is enough to see a static constructor at work.
namespace Wrox.ProCSharp.StaticConstructorSample
{
   public class UserPreferences
   {
      public static readonly Color BackColor;
            
      static UserPreferences()
      {
         DateTime now = DateTime.Now;
         if (now.DayOfWeek == DayOfWeek.Saturday
            || now.DayOfWeek == DayOfWeek.Sunday)
            BackColor = Color.Green;
         else
            BackColor = Color.Red;
      }
            
      private UserPreferences()
      {
      }
   }
}This code shows how the color preference is stored in a static variable, which is initialized in the static
constructor. This field is declared as read-only, which means that its value can only be set in a constructor.
You learn about read-only fields in more detai l later in this chapter. The code uses a few helpful st ructs that
Microsoft has supplied as part of the Framework class library: System.DateTime and System.Drawing.
Color. DateTime implements a static property — Now, which returns the current time — and an instance
property — DayOfWeek, which works out what day of the week a date-time represents. Color (which is
discussed in the online Chapter 48, “Graphics with GDI+”) is used to store colors. It implements various
static properties, such as Red and Green as used in this example, which returns commonly used colors. To
use Color, you need to reference the System.Drawing.dll assembly when compiling, and you must add a
using statement for the System.Drawing namespace:
using System;
using System.Drawing;
You test the stat ic const ructor with this code:
   class MainEntryPoint
   {
      static void Main(string[] args)
      {
         Console.WriteLine("User-preferences: BackColor is: " +
                            UserPreferences.BackColor.ToString());
      }
   }
Compiling and running this code results in this output:
User-preferences: BackColor is: Color [Red]
Of course if the code is executed during the weekend, your color preference would be Green.
Calling Constructors from Other Constructors
You may somet imes find yoursel f in the situat ion where you have several const ructors in a class , perhaps
to accommodate some optional parameters for which the constructors have some code in common. For
example, consider this:
class Car
{
   private string description;
   private uint nWheels;
   public Car(string description, uint nWheels)
   {
      this.description = description;
      this.nWheels = nWheels;
   }
            
   public Car(string description)
   {
      this.description = description;
      this.nWheels = 4;
   }
// etc.
Both constructors initialize the same fields. It would clearly be neater to place all the code in one place. C#
has a special syntax known as a constructor initializer to allow this:
class Car
{
   private string description;
   private uint nWheels;
            
   public Car(string description, uint nWheels)
   {
      this.description = description;
Classes  ❘  7778  ❘  ChaPTer 3    Objects And types
      this.nWheels = nWheels;
   }
            
   public Car(string description): this(description, 4)
   {
   }
   // etc
In this context, the this keyword simply causes the constructor with the nearest matching parameters to
be called. Note that any constructor initializer is executed before the body of the constructor. Say that the
following code is run:
Car myCar = new Car("Proton Persona");
In this example, the two-parameter constructor executes before any code in the body of the one-
parameter constructor (though in this particular case, because there is no code in the body of the 
one-parameter constructor, it makes no difference).
A C# constructor initializer may contain either one call to another constructor in the same class (using the
syntax just presented) or one call to a constructor in the immediate base class (using the same syntax, but
using the keyword base instead of this). It is not possible to put more than one call in the initializer.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值