静态类与非静态类

静态类

  继承(多态)、静态本身就是相反的。另外需要知道属性、事件其实是些特殊的方法。

  使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。 static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型。

  静态类与非静态类基本相同,但存在一个区别:静态类不能实例化。 也就是说,不能使用 new 关键字创建静态类类型的变量。 因为没有实例变量,所以要使用类名本身访问静态类的成员

  对于 只对输入参数进行运算 而不获取或设置 任何内部实例字段的方法集,静态类可以方便地用作这些方法集的容器。 例如,在 .NET Framework 类库中,静态类 System.Math 包含的方法只执行数学运算,而无需存储或检索特定 Math 类实例特有的数据。 就是说,通过指定类名称和方法名称来应用类成员。

  和所有类类型一样,当加载引用静态类的程序时,.NET Framework 公共语言运行时 (CLR) 将加载该静态类的类型信息。程序不能指定加载静态类的确切时间。 但是,可以保证在程序中首次引用该类前加载该类,并初始化该类的字段并调用其静态构造函数。 静态构造函数仅调用一次,在程序驻留的应用程序域的生存期内,静态类一直保留在内存中。

下表介绍静态类的主要特性:

  • 仅包含静态成员。
  • 无法实例化。
  • 是密封的。
  • 不能包含实例构造函数。

  因此,创建静态类与创建仅包含静态成员和私有构造函数的类基本相同。 私有构造函数阻止类被实例化。使用静态类的优点在于,编译器能够执行检查以确保不致偶然地添加实例成员。编译器将保证不会创建此类的实例。

  静态类是密封的,因此不可被继承。 它们不能从除 Object 外的任何类中继承。 静态类不能包含实例构造函数,但可以包含静态构造函数。 如果非静态类包含需要进行重要的初始化的静态成员,也应定义静态构造函数。

静态类构造函数

  静态构造函数用于初始化任何 静态 数据,或用于执行仅需执行一次的特定操作。 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数。

例如:

class SimpleClass

{   static readonly long baseline;

    static SimpleClass()

    { baseline = DateTime.Now.Ticks; }

}

  静态构造函数具有以下特点:

  • 静态构造函数既没有访问修饰符,也没有参数。
  • 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类。
  • 无法直接调用静态构造函数。
  • 在程序中,用户无法控制何时执行静态构造函数。
  • 静态构造函数的典型用途是:当类使用日志文件时,将使用这种构造函数向日志文件中写入项。
  • 静态构造函数在为非托管代码创建包装类时也很有用,此时该构造函数可以调用 LoadLibrary 方法。
  • 如果静态构造函数引发异常,运行时将不会再次调用该构造函数,并且在程序运行所在的应用程序域的生存期内,类型将保持未初始化。

静态成员

  非静态类可以包含静态的方法、字段、属性或事件。 即使没有创建类的实例,也可以调用该类中的静态成员。 始终通过类名而不是实例名称访问静态成员。 无论对一个类创建多少个实例,它的静态成员都只有一个副本。 静态方法和属性不能访问其包含类型中的非静态字段和事件,并且不能访问任何对象的实例变量(除非在方法参数中显式传递)。

  更常见的做法是声明具有一些静态成员的非静态类,而不是将整个类声明为静态类。 静态字段有两个常见的用法:一是记录已实例化对象的个数,二是存储必须在所有实例之间共享的值。

  静态方法可以被重载但不能被重写,因为它们属于类,不属于类的任何实例。

  虽然字段不能声明为 static const,但 const 字段的行为在本质上是静态的。 这样的字段属于类型,不属于类型的实例。

  C# 不支持静态局部变量(在方法范围内声明的变量)。

  通过在成员的返回类型之前使用 static 关键字可以声明静态类成员,也就是在方法的返回类型前加static。

  静态成员在第一次被访问之前并且在调用静态构造函数(如有存在)之前进行初始化。 若要访问静态类成员,应使用类名而不是变量名来指定该成员的位置。

自问自答,自娱自乐

  静态成员与实例成员的性能对比和生成调用指令的差别有哪些?

  对静态方法的调用以 Microsoft 中间语言 (MSIL) 生成调用指令,而对实例方法的调用生成 callvirt 指令,该指令还检查 null 对象引用。 但是,两者之间的性能差异在大多数时候并不明显。

  为什么静态类不能被继承?

  经反编译查看,Static内部是用sealed和abstract两个关键字组合实现的,也就是说没有static这个关键字,只是为了方便区别。

  静态类的使用和实例类中静态成员的使用技巧?

  对于 只对输入参数进行运算 而不获取或设置 任何内部实例字段的方法集,静态类可以方便地用作这些方法集的容器。也就是说,这个类只是一个工具类,里面都是些方法。

  常见的做法是声明具有一些静态成员的非静态类,而不是将整个类声明为静态类。由于无论对一个类创建多少个实例,它的静态成员都只有一个副本,所以静态字段有两个常见的用法:一是记录已实例化对象的个数,二是存储必须在所有实例之间共享的值。

  静态类和非静态类之间的包含关系?

  非静态类可以包含静态类成员,静态类只能包含静态成员。如下所示:

  Static class staticclass{//只能是静态成员};

  Class newClass{//可以包含静态成员};

  尽管类的实例包含该类所有实例字段的单独副本,但每个静态字段只有一个副本。

 静态类成员声明字段的特殊性:

class Test

{  static int x = y;

   static int y = 5;

   static void Main() {

      Console.WriteLine(Test.x);

      Console.WriteLine(Test.y);

      Test.x = 99;

      Console.WriteLine(Test.x);}

}/*Output: 0  5  99  */

  什么情况下需要在一个普通类中编写一个静态成员,而这个类不能标记static?

  当这个需要被实例化的时候,如果这个类中有一个成员是所有对象都共享的数据,这时可以将该类中的这个成员标记为静态的,但是这个类还是一个实例类。

特别需要注意的有哪些呢?   

  1. 静态成员会在整个应用程序退出时,才释放资源,所以可以在整个应用程序中共享数据。
  2. 当一个普通类添加静态字段后,系统会默认为该类生成一个静态构造函数【静态构找函数不能有访问修饰符,并且也不能带参数】
  3. 静态方法可以被重载但不能被重写,因为它们属于类,不属于类的任何实例。
  4. 不可以使用 this 来引用静态方法或属性访问器。
  5. 类和静态类可以有静态构造函数。 静态构造函数在程序开始和类实例化之间的某个时刻调用。
  6. 静态类的本质是abstract+sealed组成。静态类不能被实例化是因为abstract,不能被继承是因为sealed。
原文地址:https://www.cnblogs.com/anlen/p/3723269.html