静态类和静态类成员
静态类和类成员用于创建无需创建类的实例就能够访问的数据和函数。静态类成员可用于分离独立于任何对象标识的数据和行为:无论对象发生什么更改,这些数据和函数都不会随之变化。当类中没有依赖对象标识的数据或行为时,就可以使用静态类。
静态类
类可以声明为static的,以指示它仅包含静态成员。不能使用new关键字创建静态类的实例。静态类在加载包含该类的程序或命名空间时由.NET Framework公共语言运行库(CLR)自动加载。
使用静态类来包含不与特定对象关联的方法。例如,创建一组不操作实例数据并且不与代码中的特定对象关联的方法是很常见的要求。您应该使用静态类来包含那些方法。
静态类的主要功能如下:
l 它们仅包含静态成员。
l 它们不能被实例化。
l 它们是密封的。
l 它们不能包含实例构造函数。
因此创建静态类与创建仅包含静态成员和私有构造函数的类大致一样。私有构造函数阻止类被实例化。
使用静态类的优点在于,编译器能够执行检查以确保不致偶然地添加实例成员。编译器将保证不会创建此类的实例。
静态类是密封的,因此不可被继承。静态类不能包含构造函数,但仍可声明静态构造函数以分配初始值或设置某个静态状态。
何时使用静态类
假设有一个类CompanyInfo,它包含用于获取有关公司名称和地址信息的下列方法。
class CompanyInfo
{
public string GetCompanyName() { return "CompanyName"; }
public string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
不需要将这些方法附加到该类的具体实例。因此,您可以将它声明为静态类,而不是创建此类的不必要实例,如下所示:
static class CompanyInfo
{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
使用静态类作为不与特定对象关联的方法的组织单元。此外,静态类能够使实现更简单、迅速,因为不必创建对象就能调用其方法。以一种有意义的方式组织类内部的方法(例如System命名空间中的Math类的方法)是很有用的。
静态成员
即使没有创建类的实例,也可以调用该类中的静态方法、字段、属性或事件。如果创建了该类的任何实例,不能使用实例来访问静态成员。只存在静态字段和事件的一个副本,静态方法和属性只能访问静态字段和静态事件。静态成员通常用于表示不会随对象状态而变化的数据或计算;例如,数据库可能包含用于计算正弦和余弦的静态方法。
在成员的返回类型之前使用static关键字来声明静态类成员,例如:
public class Automobile
{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{
get
{
return 15;
}
}
public static void Drive() { }
public static event EventType RunOutOfGas;
//other non-static fields and properties...
}
静态成员在第一次被访问之前并且在任何静态构造函数(如调用的话)之前初始化。若要访问静态类成员,应使用类名而不是变量名来指定该成员的位置。
例如:
Automobile.Drive();
int i = Automobile.NumberOfWheels;
示例
下面是一个静态类的示例,它包含两个在摄氏温度和华氏温度之间执行来回转换的方法:
public static double CelsiusToFahrenheit(string temperatureCelsius){
//Conver argument to double for calculations.
double celsius = System.Double.Parse(temperatureCelsius);
//Conver Celsius to Fahrenheit
double fahrenheit = (celsius * 9 / 5) + 32;
return fahrenheit;
}
public static double FahrenheitToCelsius(string temperatureFahrenheit){
//Convert argument to double fro calculations.
double fahrenheit = System.Double.Parse(temperatureFahrenheit);
//Convert Fahrenheit to Celsius.
double celsius = (fahrenheit - 32) * 5 / 9;
return celsius;
}
}
class TestTemperatureConverter {
static void Main(){
System.Console.WriteLine("Please select the convertor direction");
System.Console.WriteLine("1. From Celsius to Fahrenheit.");
System.Console.WriteLine("2. From Fahrenheit to Celsius.");
string selection = System.Console.ReadLine();
double F,C = 0;
switch(selection){
case "1":
System.Console.Write("Please enter the Celsius temperature: ");
F = TemperatureConverter.CelsiusToFahrenheit(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Fahrenheit: {0:F2}",F);
break;
case "2":
System.Console.Write("Please enter the Fahrenheit temperature: ");
C = TemperatureConverter.FahrenheitToCelsius(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Celsius: {0:F2}",C);
break;
default:
System.Console.WriteLine("Please select a vonvertor.");
break;
}
}
}
如何:了解向方法传递结构和向方法传递类引用之间的区别
本示例演示的向方法传递结构时,传递的是该结构的副本,而在传递类实例时,传递的是一个引用。
本示例的输出表明:当向ClassTaker方法传递类实例时,之更改类字段的值。但是向StructTaker方法传递结构实例并不更改结构字段。这是因为向StructTaker方法传递的是结构的副本,而向ClassTaker方法传递的是对类的引用。
public string willIChange;
}
struct TheStruct {
public string willIChange;
}
class TestClassAndStruct {
static void ClassTaker(TheClass c){
c.willIChange = "Changed";
}
static void StructTaker(TheStruct s){
s.willIChange = "Changed";
}
static void Main(){
TheClass testClass = new TheClass();
TheStruct testStruct = new TheStruct();
testClass.willIChange = "Not Changed";
testStruct.willIChange = "Not Changed";
ClassTaker(testClass);
StructTaker(testStruct);
System.Console.WriteLine("Class field = {0}",testClass.willIChange);
System.Console.WriteLine("Struct field = {0}",testStruct.willIChange);
}
}