使用 static 修饰符声明属于类型自己而不是属于特定对象的静态成员。 static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类之外的类型。 有关更多信息,请参见 静态类和静态类成员(C# 编程指南)。 编程
示例 c#
下面的类声明为 static,而且只包含 static 方法:xss
static class CompanyEmployee
{
public static void DoSomething() { /*...*/ }
public static void DoSomethingElse() { /*...*/ }
}
常数或者类型声明隐式地是静态成员。ide
不能经过实例引用静态成员。 然而,能够经过类型名称引用它。 例如,请考虑如下类: 函数
public class MyBaseC
{
public struct MyStruct
{
public static int x = 100;
}
}
若要引用静态成员 x,请使用彻底限定名 MyBaseC.MyStruct.x,除非可从相同范围访问成员:ui
Console.WriteLine(MyBaseC.MyStruct.x);
尽管类的实例包含该类全部实例字段的单独副本,但每一个静态字段只有一个副本。this
不能够使用 this 来引用静态方法或属性访问器。spa
若是对类应用 static 关键字,则该类的全部成员都必须是静态的。版本控制
类和静态类能够有静态构造函数。 静态构造函数在程序开始和类实例化之间的某个时刻调用。
指针
此示例说明:虽然能够用另外一个还没有声明的静态字段实例化一个静态字段,但直到向后者显式赋值后,才能肯定结果。
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
*/
abstract 修饰符指示所修饰的内容缺乏实现或未彻底实现。 abstract 修饰符可用于类、方法、属性、索引器和事件。 在类声明中使用 abstract 修饰符以指示某个类只能是其余类的基类。 标记为抽象或包含在抽象类中的成员必须经过从抽象类派生的类来实现。
abstract class ShapesClass { abstract public int Area(); } class Square : ShapesClass { int side = 0; public Square(int n) { side = n; } // Area method is required to avoid // a compile-time error. public override int Area() { return side * side; } static void Main() { Square sq = new Square(12); Console.WriteLine("Area of the square = {0}", sq.Area()); } interface I { void M(); } abstract class C : I { public abstract void M(); } } // Output: Area of the square = 144
抽象类具备如下特性:
抽象类不能实例化。
抽象类能够包含抽象方法和抽象访问器。
不能用 sealed(C# 参考) 修饰符修饰抽象类,由于这两个修饰符的含义是相反的。 采用 sealed 修饰符的类没法继承,而 abstract 修饰符要求对类进行继承。
从抽象类派生的非抽象类必须包括继承的全部抽象方法和抽象访问器的实际实现。
在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。
抽象方法具备如下特性:
抽象方法是隐式的虚方法。
只容许在抽象类中使用抽象方法声明。
由于抽象方法声明不提供实际的实现,因此没有方法体;方法声明只是以一个分号结束,而且在签名后没有大括号 ({ })。 例如:
public abstract void MyMethod();
实现由一个重写方法override(C# 参考)提供,此重写方法是非抽象类的一个成员。
除了在声明和调用语法上不一样外,抽象属性的行为与抽象方法同样。
在静态属性上使用 abstract 修饰符是错误的。
在派生类中,经过包括使用 override 修饰符的属性声明,能够重写抽象的继承属性。
有关抽象类的更多信息,请参见抽象类、密封类及类成员(C# 编程指南)。
抽象类必须为全部接口成员提供实现。
实现接口的抽象类能够将接口方法映射到抽象方法上。 例如:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
base有两种用法
base 关键字用于从派生类中访问基类的成员:
调用基类上已被其余方法重写的方法。
指定建立派生类实例时应调用的基类构造函数。
基类访问只能在构造函数、实例方法或实例属性访问器中进行。
从静态方法中使用 base 关键字是错误的。
所访问的基类是类声明中指定的基类。 例如,若是指定 class ClassB : ClassA,则不管 ClassA 的基类如何,从 ClassB 上访问 ClassA 的成员。
在本例中,基类 Person 和派生类 Employee 都有一个名为 Getinfo 的方法。 经过使用 base 关键字,能够从派生类中调用基类的 Getinfo 方法。
public class Person { protected string ssn = "444-55-6666"; protected string name = "John L. Malgraine"; public virtual void GetInfo() { Console.WriteLine("Name: {0}", name); Console.WriteLine("SSN: {0}", ssn); } } class Employee : Person { public string id = "ABC567EFG"; public override void GetInfo() { // Calling the base class GetInfo method: base.GetInfo(); Console.WriteLine("Employee ID: {0}", id); } } class TestClass { static void Main() { Employee E = new Employee(); E.GetInfo(); } } /* Output Name: John L. Malgraine SSN: 444-55-6666 Employee ID: ABC567EFG */
有关其余示例,请参见 new、virtual 和 override。
本示例显示如何指定在建立派生类实例时调用的基类构造函数。
没个类其实都有一个默认的构造函数,若是被覆盖了,在父类中没有一个空的构造函数,则子类中也不能有空的构造函数,必须继承父类中的构造函数。
public class BaseClass { int num; public BaseClass() { Console.WriteLine("in BaseClass()"); } public BaseClass(int i) { num = i; Console.WriteLine("in BaseClass(int i)"); } public int GetNum() { return num; } } public class DerivedClass : BaseClass { // This constructor will call BaseClass.BaseClass() public DerivedClass() : base() { } // This constructor will call BaseClass.BaseClass(int i) public DerivedClass(int i) : base(i) { } static void Main() { DerivedClass md = new DerivedClass(); DerivedClass md1 = new DerivedClass(1); } }/* Output: in BaseClass() in BaseClass(int i) */
this 关键字引用类的当前实例,还可用做扩展方法的第一个参数的修饰符。
![]() |
---|
本文讨论对类实例使用 this。 有关其在扩展方法中使用的更多信息,请参见扩展方法(C# 编程指南)。 |
如下是 this 的经常使用用途:
限定被类似的名称隐藏的成员,例如:
public Employee(string name, string alias) { // Use this to qualify the fields, name and alias: this.name = name; this.alias = alias; }
将对象做为参数传递到其余方法,例如:
CalcTax(this);
声明索引器,例如:
public int this[int param] { get { return array[param]; } set { array[param] = value; } }
因为静态成员函数存在于类一级,而且不是对象的一部分,所以没有 this 指针。 在静态方法中引用 this 是错误的。
virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们能够在派生类中被重写。 例如,此方法可被任何继承它的类重写。
public virtual double Area() { return x * y; }
虚拟成员的实现可由派生类中的重写成员更改。 有关如何使用 virtual 关键字的更多信息,请参见使用 Override 和 New 关键字进行版本控制(C# 编程指南)和了解什么时候使用 Override 和 New 关键字(C# 编程指南)。
调用虚方法时,将为重写成员检查该对象的运行时类型。 将调用大部分派生类中的该重写成员,若是没有派生类重写该成员,则它多是原始成员。
默认状况下,方法是非虚拟的。 不能重写非虚方法。
virtual 修饰符不能与 static、abstract, private 或 override 修饰符一块儿使用。 下面的示例演示一个虚拟属性:
class MyBaseClass
{
// virtual auto-implemented property. Overrides can only
// provide specialized behavior if they implement get and set accessors.
public virtual string Name { get; set; }
// ordinary virtual property with backing field
private int num;
public virtual int Number
{
get { return num; }
set { num = value; }
}
}
class MyDerivedClass : MyBaseClass
{
private string name;
// Override auto-implemented property with ordinary property
// to provide specialized accessor behavior.
public override string Name
{
get
{
return name;
}
set
{
if (value != String.Empty)
{
name = value;
}
else
{
name = "Unknown";
}
}
}
}
除了声明和调用语法不一样外,虚拟属性的行为与抽象方法同样。
在静态属性上使用 virtual 修饰符是错误的。
经过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。