使用 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 修飾符的屬性聲明,可在派生類中重寫虛擬繼承屬性。