網(wǎng)站首頁 編程語言 正文
上文c#語言入門類型和成員中介紹的類型是使用以下構(gòu)建基塊生成的:成員*_、表達(dá)式和語句_*。
1、成員
class 的成員要么是靜態(tài)成員,要么是實(shí)例成員。 靜態(tài)成員屬于類,而實(shí)例成員則屬于對象(類實(shí)例)。
以下列表概述了類可以包含的成員類型:
- 常量:與類相關(guān)聯(lián)的常量值
- 字段:與類關(guān)聯(lián)的變量
- 方法:類可執(zhí)行的操作
- 屬性:與讀取和寫入類的已命名屬性相關(guān)聯(lián)的操作
- 索引器:與將類實(shí)例編入索引(像處理數(shù)組一樣)相關(guān)聯(lián)的操作
- 事件:類可以生成的通知
- 運(yùn)算符:類支持的轉(zhuǎn)換和表達(dá)式運(yùn)算符
- 構(gòu)造函數(shù):初始化類實(shí)例或類本身所需的操作
- 終結(jié)器:永久放棄類的實(shí)例之前完成的操作
-
類型:類聲明的嵌套類型
2、輔助功能
每個(gè)類成員都有關(guān)聯(lián)的可訪問性,用于控制能夠訪問成員的程序文本區(qū)域。 可訪問性有六種可能的形式。
以下內(nèi)容對訪問修飾符進(jìn)行了匯總:
public
:訪問不受限制。private
:訪問僅限于此類。protected
:訪問僅限于此類或派生自此類的類。internal
:僅可訪問當(dāng)前程序集(.exe 或 .dll)。protected internal
:僅可訪問此類、從此類中派生的類,或者同一程序集中的類。private protected
:僅可訪問此類或同一程序集中從此類中派生的類。
3、字段
字段 是與類或類實(shí)例相關(guān)聯(lián)的變量。
使用靜態(tài)修飾符聲明的字段定義的是靜態(tài)字段。 靜態(tài)字段只指明一個(gè)存儲位置。 無論創(chuàng)建多少個(gè)類實(shí)例,永遠(yuǎn)只有一個(gè)靜態(tài)字段副本。
不使用靜態(tài)修飾符聲明的字段定義的是實(shí)例字段。 每個(gè)類實(shí)例均包含相應(yīng)類的所有實(shí)例字段的單獨(dú)副本。
在以下示例中,每個(gè) Color 類實(shí)例均包含 R、G 和 B 實(shí)例字段的單獨(dú)副本,但只包含 Black
、White
、Red
、Green
和 Blue
靜態(tài)字段的一個(gè)副本:
public class Color { public static readonly Color Black = new(0, 0, 0); public static readonly Color White = new(255, 255, 255); public static readonly Color Red = new(255, 0, 0); public static readonly Color Green = new(0, 255, 0); public static readonly Color Blue = new(0, 0, 255); public byte R; public byte G; public byte B; public Color(byte r, byte g, byte b) { R = r; G = g; B = b; } }
如上面的示例所示:可以使用 readonly
修飾符聲明 只讀字段。 只能在字段聲明期間或在同一個(gè)類的構(gòu)造函數(shù)中向只讀字段賦值。
4、方法
方法 是實(shí)現(xiàn)對象或類可執(zhí)行的計(jì)算或操作的成員。 靜態(tài)方法 是通過類進(jìn)行訪問。 實(shí)例方法 是通過類實(shí)例進(jìn)行訪問。
方法可能包含一個(gè)參數(shù)列表,這些參數(shù)表示傳遞給方法的值或變量引用。 方法具有返回類型,它用于指定方法計(jì)算和返回的值的類型。 如果方法未返回值,則它的返回類型為 void。
方法可能也包含一組類型參數(shù),必須在調(diào)用方法時(shí)指定類型自變量,這一點(diǎn)與類型一樣。 與類型不同的是,通常可以根據(jù)方法調(diào)用的自變量推斷出類型自變量,無需顯式指定。
在聲明方法的類中,方法的 簽名 必須是唯一的。 方法簽名包含方法名稱、類型參數(shù)數(shù)量及其參數(shù)的數(shù)量、修飾符和類型。 方法簽名不包含返回類型。
當(dāng)方法主體是單個(gè)表達(dá)式時(shí),可使用緊湊表達(dá)式格式定義方法,如下例中所示:
public override string ToString() => "This is an object";
4.1參數(shù)
參數(shù)用于將值或變量引用傳遞給方法。 方法參數(shù)從調(diào)用方法時(shí)指定的 自變量 中獲取其實(shí)際值。 有
四類參數(shù):值參數(shù)、引用參數(shù)、輸出參數(shù)和參數(shù)數(shù)組。
值參數(shù)用于傳遞輸入自變量。 值參數(shù)對應(yīng)于局部變量,從為其傳遞的自變量中獲取初始值。 修改值形參不會影響為其傳遞的實(shí)參。
可以指定默認(rèn)值,從而省略相應(yīng)的自變量,這樣值參數(shù)就是可選的。
引用參數(shù)用于按引用傳遞自變量。 為引用參數(shù)傳遞的自變量必須是一個(gè)帶有明確值的變量。 在方法執(zhí)行期間,引用參數(shù)指出的存儲位置與自變量相同。 引用參數(shù)使用 ref 修飾符進(jìn)行聲明。 下面的示例展示了如何使用 ref 參數(shù)。
static void Swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } public static void SwapExample() { int i = 1, j = 2; Swap(ref i, ref j); Console.WriteLine($"{i} {j}"); // "2 1" }
輸出參數(shù)用于按引用傳遞自變量。 輸出參數(shù)與引用參數(shù)類似,不同之處在于,不要求向調(diào)用方提供的自變量顯式賦值。 輸出參數(shù)使用 out 修飾符進(jìn)行聲明。 下面的示例演示如何通過 C# 7
中引入的語法使用 out 參數(shù)。
static void Divide(int x, int y, out int result, out int remainder) { result = x / y; remainder = x % y; } public static void OutUsage() { Divide(10, 3, out int res, out int rem); Console.WriteLine($"{res} {rem}"); // "3 1" }
參數(shù)數(shù)組 允許向方法傳遞數(shù)量不定的自變量。 參數(shù)數(shù)組使用 params 修飾符進(jìn)行聲明。 參數(shù)數(shù)組只能是方法的最后一個(gè)參數(shù),且參數(shù)數(shù)組的類型必須是一維數(shù)組類型。 System.Console
類的 Write
和 WriteLine
方法是參數(shù)數(shù)組用法的典型示例。 它們的聲明方式如下。
public class Console { public static void Write(string fmt, params object[] args) { } public static void WriteLine(string fmt, params object[] args) { } // ... }
在使用參數(shù)數(shù)組的方法中,參數(shù)數(shù)組的行為與數(shù)組類型的常規(guī)參數(shù)完全相同。 不過,在調(diào)用包含形參數(shù)組的方法時(shí),要么可以傳遞形參數(shù)組類型的一個(gè)實(shí)參,要么可以傳遞形參數(shù)組的元素類型的任意數(shù)量實(shí)參。 在后一種情況中,數(shù)組實(shí)例會自動創(chuàng)建,并初始化為包含給定的自變量。
以下示例:
int x, y, z; x = 3; y = 4; z = 5; Console.WriteLine("x={0} y={1} z={2}", x, y, z);
等同于編寫以下代碼:
int x = 3, y = 4, z = 5; string s = "x={0} y={1} z={2}"; object[] args = new object[3]; args[0] = x; args[1] = y; args[2] = z; Console.WriteLine(s, args);
4.2方法主體和局部變量
方法主體指定了在調(diào)用方法時(shí)執(zhí)行的語句。
方法主體可以聲明特定于方法調(diào)用的變量。 此類變量稱為 局部變量。 局部變量聲明指定了類型名稱、變量名稱以及可能的初始值。 下面的示例聲明了初始值為零的局部變量 i 和無初始值的局部變量 j。
class Squares { public static void WriteSquares() { int i = 0; int j; while (i < 10) { j = i * i; Console.WriteLine($"{i} x {i} = {j}"); i++; } } }
C# 要求必須先 明確賦值 局部變量,然后才能獲取其值。 例如,如果上述 i 的聲明未包含初始值,那么編譯器會在后續(xù)使用 i 時(shí)報(bào)告錯(cuò)誤,因?yàn)樵诤罄m(xù)使用時(shí) i 不會在程序中得到明確賦值。
方法可以使用 return
語句將控制權(quán)返回給調(diào)用方。 在返回 void
的方法中,return 語句無法指定表達(dá)式。 在不返回 void 的方法中,return 語句必須包括用于計(jì)算返回值的表達(dá)式。
4.3靜態(tài)和實(shí)例方法
使用 static
修飾符聲明的方法是靜態(tài)方法。 靜態(tài)方法不對特定的實(shí)例起作用,只能直接訪問靜態(tài)成員。
未使用 static 修飾符聲明的方法是實(shí)例方法。 實(shí)例方法對特定的實(shí)例起作用,并能夠訪問靜態(tài)和實(shí)例成員。 其中調(diào)用實(shí)例方法的實(shí)例可以作為 this 顯式訪問。 在靜態(tài)方法中引用 this 會生成錯(cuò)誤。
以下 Entity 類包含靜態(tài)和實(shí)例成員:
class Entity { static int s_nextSerialNo; int _serialNo; public Entity() { _serialNo = s_nextSerialNo++; } public int GetSerialNo() { return _serialNo; } public static int GetNextSerialNo() { return s_nextSerialNo; } public static void SetNextSerialNo(int value) { s_nextSerialNo = value; } }
每個(gè) Entity 實(shí)例均有一個(gè)序列號(很可能包含此處未顯示的其他一些信息)。 Entity 構(gòu)造函數(shù)(類似于實(shí)例方法)將新實(shí)例初始化為包含下一個(gè)可用的序列號。 由于構(gòu)造函數(shù)是實(shí)例成員,因此可以訪問 _serialNo
實(shí)例字段和 s_nextSerialNo
靜態(tài)字段。
GetNextSerialNo
和 SetNextSerialNo
靜態(tài)方法可以訪問 s_nextSerialNo
靜態(tài)字段,但如果直接訪問 _serialNo 實(shí)例字段,則會生成錯(cuò)誤。
下例顯示了 Entity 類的用法:
Entity.SetNextSerialNo(1000); Entity e1 = new(); Entity e2 = new(); Console.WriteLine(e1.GetSerialNo()); // Outputs "1000" Console.WriteLine(e2.GetSerialNo()); // Outputs "1001" Console.WriteLine(Entity.GetNextSerialNo()); // Outputs "1002"
SetNextSerialNo
和 GetNextSerialNo
靜態(tài)方法在類中進(jìn)行調(diào)用,而 GetSerialNo
實(shí)例方法則是在類實(shí)例中進(jìn)行調(diào)用,
4.4虛方法、重寫方法和抽象方法
可使用虛方法、重寫方法和抽象方法來定義類類型層次結(jié)構(gòu)的行為。 由于類可從基類派生,因此這些派生類可能需要修改在基類中實(shí)現(xiàn)的行為。 虛方法是在基類中聲明和實(shí)現(xiàn)的方法,其中任何派生類都可提供更具體的實(shí)現(xiàn)。 重寫方法是在派生類中實(shí)現(xiàn)的方法,可修改基類實(shí)現(xiàn)的行為。 抽象方法是在基類中聲明的方法,必須在所有派生類中重寫。 事實(shí)上,抽象方法不在基類中定義實(shí)現(xiàn)。
對實(shí)例方法的方法調(diào)用可解析為基類或派生類實(shí)現(xiàn)。 變量的類型確定了其編譯時(shí)類型。 編譯時(shí)類型是編譯器用于確定其成員的類型。 但是,可將變量分配給從其編譯時(shí)類型派生的任何類型的實(shí)例。 運(yùn)行時(shí)間類型是變量所引用的實(shí)際實(shí)例的類型。
調(diào)用虛方法時(shí),為其調(diào)用方法的實(shí)例的 運(yùn)行時(shí)類型 決定了要調(diào)用的實(shí)際方法實(shí)現(xiàn)代碼。 調(diào)用非虛方法時(shí),實(shí)例的 編譯時(shí)類型 是決定性因素。
可以在派生類中 重寫 虛方法。 如果實(shí)例方法聲明中有 override 修飾符,那么實(shí)例方法可以重寫簽名相同的繼承虛方法。 虛方法聲明引入了新方法。 重寫方法聲明通過提供現(xiàn)有繼承的虛方法的新實(shí)現(xiàn),專門針對該方法。
抽象方法 是沒有實(shí)現(xiàn)代碼的虛方法。 抽象方法使用 abstract 修飾符進(jìn)行聲明,僅可在抽象類中使用。 必須在所有非抽象派生類中重寫抽象方法。
下面的示例聲明了一個(gè)抽象類 Expression
,用于表示表達(dá)式樹節(jié)點(diǎn);還聲明了三個(gè)派生類(Constant、VariableReference 和 Operation),用于實(shí)現(xiàn)常量、變量引用和算術(shù)運(yùn)算的表達(dá)式樹節(jié)點(diǎn)。 (該示例與表達(dá)式樹類型相似,但與它無關(guān))。
public abstract class Expression { public abstract double Evaluate(Dictionary<string, object> vars); } public class Constant : Expression { double _value; public Constant(double value) { _value = value; } public override double Evaluate(Dictionary<string, object> vars) { return _value; } } public class VariableReference : Expression { string _name; public VariableReference(string name) { _name = name; } public override double Evaluate(Dictionary<string, object> vars) { object value = vars[_name] ?? throw new Exception($"Unknown variable: {_name}"); return Convert.ToDouble(value); } } public class Operation : Expression { Expression _left; char _op; Expression _right; public Operation(Expression left, char op, Expression right) { _left = left; _op = op; _right = right; } public override double Evaluate(Dictionary<string, object> vars) { double x = _left.Evaluate(vars); double y = _right.Evaluate(vars); switch (_op) { case '+': return x + y; case '-': return x - y; case '*': return x * y; case '/': return x / y; default: throw new Exception("Unknown operator"); } } }
上面的四個(gè)類可用于進(jìn)行算術(shù)表達(dá)式建模。 例如,使用這些類的實(shí)例,可以按如下方式表示表達(dá)式 x + 3。
Expression e = new Operation( new VariableReference("x"), '+', new Constant(3));
調(diào)用 Expression
實(shí)例的 Evaluate
方法可以計(jì)算給定的表達(dá)式并生成 double
值。 此方法需要使用自變量 Dictionary,其中包含變量名稱(作為項(xiàng)鍵)和值(作為項(xiàng)值)。 因?yàn)?Evaluate
是一個(gè)抽象方法,因此派生自 Expression
的非抽象類必須替代 Evaluate。
Constant 的 Evaluate
實(shí)現(xiàn)代碼只返回存儲的常量。 VariableReference
實(shí)現(xiàn)代碼查找字典中的變量名稱,并返回結(jié)果值。 Operation 實(shí)現(xiàn)代碼先計(jì)算左右操作數(shù)(以遞歸方式調(diào)用其 Evaluate 方法),然后執(zhí)行給定的算術(shù)運(yùn)算。
以下程序使用 Expression 類根據(jù)不同的 x 和 y 值計(jì)算表達(dá)式 x * (y + 2):
Expression e = new Operation( new VariableReference("x"), '*', new Operation( new VariableReference("y"), '+', new Constant(2) ) ); Dictionary<string, object> vars = new(); vars["x"] = 3; vars["y"] = 5; Console.WriteLine(e.Evaluate(vars)); // "21" vars["x"] = 1.5; vars["y"] = 9; Console.WriteLine(e.Evaluate(vars)); // "16.5"
4.5方法重載
借助方法 重載,同一類中可以有多個(gè)同名的方法,只要這些方法具有唯一簽名即可。 編譯如何調(diào)用重載的方法時(shí),編譯器使用 重載決策 來確定要調(diào)用的特定方法。 重載決策會查找與自變量匹配度最高的一種方法。 如果找不到任何最佳匹配項(xiàng),則會報(bào)告錯(cuò)誤。 下面的示例展示了重載決策的實(shí)際工作方式。 UsageExample
方法中每個(gè)調(diào)用的注釋指明了調(diào)用的方法。
class OverloadingExample { static void F() => Console.WriteLine("F()"); static void F(object x) => Console.WriteLine("F(object)"); static void F(int x) => Console.WriteLine("F(int)"); static void F(double x) => Console.WriteLine("F(double)"); static void F<T>(T x) => Console.WriteLine("F<T>(T)"); static void F(double x, double y) => Console.WriteLine("F(double, double)"); public static void UsageExample() { F(); // Invokes F() F(1); // Invokes F(int) F(1.0); // Invokes F(double) F("abc"); // Invokes F<string>(string) F((double)1); // Invokes F(double) F((object)1); // Invokes F(object) F<int>(1); // Invokes F<int>(int) F(1, 1); // Invokes F(double, double) } }
如示例所示,可將自變量顯式轉(zhuǎn)換成確切的參數(shù)類型和類型自變量,隨時(shí)選擇特定的方法。
5、其他函數(shù)成員
包含可執(zhí)行代碼的成員統(tǒng)稱為類的 函數(shù)成員。 上一部分介紹了作為主要函數(shù)成員類型的方法。 此部分將介紹 C# 支持的其他類型函數(shù)成員:構(gòu)造函數(shù)、屬性、索引器、事件、運(yùn)算符和終結(jié)器。
下面的示例展示了 MyList<T>
泛型類,用于實(shí)現(xiàn)對象的可擴(kuò)充列表。 此類包含最常見類型函數(shù)成員的多個(gè)示例。
public class MyList<T> { const int DefaultCapacity = 4; T[] _items; int _count; public MyList(int capacity = DefaultCapacity) { _items = new T[capacity]; } public int Count => _count; public int Capacity { get => _items.Length; set { if (value < _count) value = _count; if (value != _items.Length) { T[] newItems = new T[value]; Array.Copy(_items, 0, newItems, 0, _count); _items = newItems; } } } public T this[int index] { get => _items[index]; set { _items[index] = value; OnChanged(); } } public void Add(T item) { if (_count == Capacity) Capacity = _count * 2; _items[_count] = item; _count++; OnChanged(); } protected virtual void OnChanged() => Changed?.Invoke(this, EventArgs.Empty); public override bool Equals(object other) => Equals(this, other as MyList<T>); static bool Equals(MyList<T> a, MyList<T> b) { if (Object.ReferenceEquals(a, null)) return Object.ReferenceEquals(b, null); if (Object.ReferenceEquals(b, null) || a._count != b._count) return false; for (int i = 0; i < a._count; i++) { if (!object.Equals(a._items[i], b._items[i])) { return false; } } return true; } public event EventHandler Changed; public static bool operator ==(MyList<T> a, MyList<T> b) => Equals(a, b); public static bool operator !=(MyList<T> a, MyList<T> b) => !Equals(a, b); }
5.1構(gòu)造函數(shù)
C# 支持實(shí)例和靜態(tài)構(gòu)造函數(shù)。 實(shí)例構(gòu)造函數(shù) 是實(shí)現(xiàn)初始化類實(shí)例所需執(zhí)行的操作的成員。 靜態(tài)構(gòu)造函數(shù)是實(shí)現(xiàn)在首次加載類時(shí)初始化類本身所需執(zhí)行的操作的成員。
構(gòu)造函數(shù)的聲明方式與方法一樣,都沒有返回類型,且與所含類同名。 如果構(gòu)造函數(shù)聲明包含 static 修飾符,則聲明的是靜態(tài)構(gòu)造函數(shù)。 否則,聲明的是實(shí)例構(gòu)造函數(shù)。
實(shí)例構(gòu)造函數(shù)可重載并且可具有可選參數(shù)。 例如,MyList<T>
類聲明一個(gè)具有單個(gè)可選 int 參數(shù)的實(shí)例構(gòu)造函數(shù)。 實(shí)例構(gòu)造函數(shù)使用 new 運(yùn)算符進(jìn)行調(diào)用。 下面的語句使用包含和不包含可選自變量的 MyList 類構(gòu)造函數(shù)來分配兩個(gè) MyList<string>
實(shí)例。
MyList<string> list1 = new(); MyList<string> list2 = new(10);
與其他成員不同,實(shí)例構(gòu)造函數(shù)不會被繼承。 類中只能包含實(shí)際上已在該類中聲明的實(shí)例構(gòu)造函數(shù)。 如果沒有為類提供實(shí)例構(gòu)造函數(shù),則會自動提供不含參數(shù)的空實(shí)例構(gòu)造函數(shù)。
5.2“屬性”
屬性 是字段的自然擴(kuò)展。 兩者都是包含關(guān)聯(lián)類型的已命名成員,用于訪問字段和屬性的語法也是一樣的。 不過,與字段不同的是,屬性不指明存儲位置。 相反,屬性包含訪問器,用于指定在讀取或?qū)懭雽傩灾禃r(shí)執(zhí)行的語句。 get 訪問器讀取該值。 set 訪問器寫入該值。
屬性的聲明方式與字段相似,區(qū)別是屬性聲明以在分隔符 { 和 } 之間寫入的 get 訪問器或 set 訪問器結(jié)束,而不是以分號結(jié)束。 同時(shí)具有 get 訪問器和 set 訪問器的屬性是“讀寫屬性”。 只有 get 訪問器的屬性是“只讀屬性”。 只有 set 訪問器的屬性是“只寫屬性”。
get 訪問器對應(yīng)于包含屬性類型的返回值的無參數(shù)方法。 set 訪問器對應(yīng)于包含一個(gè)名為 value 的參數(shù)但不含返回類型的方法。 get 訪問器會計(jì)算屬性的值。 set 訪問器會為屬性提供新值。 當(dāng)屬性是賦值的目標(biāo),或者是 ++
或 --
的操作數(shù)時(shí),會調(diào)用 set 訪問器。 在引用了屬性的其他情況下,會調(diào)用 get 訪問器。
MyList<T> 類聲明以下兩個(gè)屬性:Count
和 Capacity
(分別為只讀和讀寫)。
以下示例代碼展示了如何使用這些屬性:
MyList<string> names = new(); names.Capacity = 100; // Invokes set accessor int i = names.Count; // Invokes get accessor int j = names.Capacity; // Invokes get accessor
類似于字段和方法,C# 支持實(shí)例屬性和靜態(tài)屬性。 靜態(tài)屬性使用靜態(tài)修飾符進(jìn)行聲明,而實(shí)例屬性則不使用靜態(tài)修飾符進(jìn)行聲明。
屬性的訪問器可以是虛的。 如果屬性聲明包含 virtual
、abstract
或 override
修飾符,則適用于屬性的訪問器。
5.3索引器
借助 索引器 成員,可以將對象編入索引(像處理數(shù)組一樣)。 索引器的聲明方式與屬性類似,不同之處在于,索引器成員名稱格式為 this 后跟在分隔符 [ 和 ] 內(nèi)寫入的參數(shù)列表。 這些參數(shù)在索引器的訪問器中可用。 類似于屬性,索引器分為讀寫、只讀和只寫索引器,且索引器的訪問器可以是虛的。
MyList<T> 類聲明一個(gè)需要使用 int 參數(shù)的讀寫索引器。 借助索引器,可以使用 int 值將 MyList<T> 實(shí)例編入索引。
?例如:
MyList<string> names = new(); names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); for (int i = 0; i < names.Count; i++) { string s = names[i]; names[i] = s.ToUpper(); }
索引器可被重載。 一個(gè)類可聲明多個(gè)索引器,只要其參數(shù)的數(shù)量或類型不同即可。
5.4事件
借助 事件 成員,類或?qū)ο罂梢蕴峁┩ㄖ?事件的聲明方式與字段類似,區(qū)別是事件聲明包括 event
關(guān)鍵字,且類型必須是委托類型。
在聲明事件成員的類中,事件的行為與委托類型的字段完全相同(前提是事件不是抽象的,且不聲明訪問器)。 字段存儲對委托的引用,委托表示已添加到事件的事件處理程序。 如果沒有任何事件處理程序,則字段為 null。
MyList<T> 類聲明一個(gè) Changed 事件成員,指明已向列表添加了新項(xiàng)。 Changed 事件由 OnChanged 虛方法引發(fā),此方法會先檢查事件是否是 null(即不含任何處理程序)。 引發(fā)事件的概念恰恰等同于調(diào)用由事件表示的委托。 不存在用于引發(fā)事件的特殊語言構(gòu)造。
客戶端通過 事件處理程序 響應(yīng)事件。 使用 += 和 -= 運(yùn)算符分別可以附加和刪除事件處理程序。 下面的示例展示了如何向 MyList<string>
的 Changed
事件附加事件處理程序。
class EventExample { static int s_changeCount; static void ListChanged(object sender, EventArgs e) { s_changeCount++; } public static void Usage() { var names = new MyList<string>(); names.Changed += new EventHandler(ListChanged); names.Add("Liz"); names.Add("Martha"); names.Add("Beth"); Console.WriteLine(s_changeCount); // "3" } }
對于需要控制事件的基礎(chǔ)存儲的高級方案,事件聲明可以顯式提供 add 和 remove 訪問器,這與屬性的 set 訪問器類似。
5.5運(yùn)算符
運(yùn)算符 是定義向類實(shí)例應(yīng)用特定表達(dá)式運(yùn)算符的含義的成員。 可以定義三種類型的運(yùn)算符:一元運(yùn)算符、二元運(yùn)算符和轉(zhuǎn)換運(yùn)算符。 所有運(yùn)算符都必須聲明為 public 和 static。
MyList<T> 類會聲明兩個(gè)運(yùn)算符:operator ==
和 operator !=。
對于向 MyList 實(shí)例應(yīng)用這些運(yùn)算符的表達(dá)式來說,這些重寫的運(yùn)算符向它們賦予了新的含義。 具體而言,這些運(yùn)算符定義的是兩個(gè) MyList<T> 實(shí)例的相等性(使用其 Equals 方法比較所包含的每個(gè)對象)。 下面的示例展示了如何使用 == 運(yùn)算符比較兩個(gè) MyList<int> 實(shí)例。
MyList<int> a = new(); a.Add(1); a.Add(2); MyList<int> b = new(); b.Add(1); b.Add(2); Console.WriteLine(a == b); // Outputs "True" b.Add(3); Console.WriteLine(a == b); // Outputs "False"
第一個(gè) Console.WriteLine
輸出 True,因?yàn)閮蓚€(gè)列表包含的對象不僅數(shù)量相同,而且值和順序也相同。 如果 MyList<T> 未定義 operator ==,
那么第一個(gè) Console.WriteLine
會輸出 False,因?yàn)?a 和 b 引用不同的 MyList<int> 實(shí)例。
5.6終結(jié)器
終結(jié)器 是實(shí)現(xiàn)完成類實(shí)例所需的操作的成員。 通常,需要使用終結(jié)器來釋放非托管資源。 終結(jié)器既不能包含參數(shù)和可訪問性修飾符,也不能進(jìn)行顯式調(diào)用。 實(shí)例的終結(jié)器在垃圾回收期間自動調(diào)用。 有關(guān)詳細(xì)信息,請參閱有關(guān)終結(jié)器的文章。
垃圾回收器在決定何時(shí)收集對象和運(yùn)行終結(jié)器時(shí)有很大自由度。 具體而言,終結(jié)器的調(diào)用時(shí)間具有不確定性,可以在任意線程上執(zhí)行終結(jié)器。 因?yàn)檫@樣或那樣的原因,只有在沒有其他可行的解決方案時(shí),類才能實(shí)現(xiàn)終結(jié)器。
處理對象析構(gòu)的更好方法是使用 using 語句。
6、表達(dá)式
表達(dá)式 是在 操作數(shù) 和 運(yùn)算符 的基礎(chǔ)之上構(gòu)造而成。 表達(dá)式的運(yùn)算符指明了向操作數(shù)應(yīng)用的運(yùn)算。 運(yùn)算符的示例包括 +
、-
、*
、/ 和 new。 操作數(shù)的示例包括文本、字段、局部變量和表達(dá)式。
如果某個(gè)表達(dá)式包含多個(gè)運(yùn)算符,則運(yùn)算符的優(yōu)先順序控制各個(gè)運(yùn)算符的計(jì)算順序。
例如,表達(dá)式 x + y * z
相當(dāng)于計(jì)算 x + (y * z),
因?yàn)?* 運(yùn)算符的優(yōu)先級高于 + 運(yùn)算符。
如果操作數(shù)兩邊的兩個(gè)運(yùn)算符的優(yōu)先級相同,那么運(yùn)算符的 結(jié)合性 決定了運(yùn)算的執(zhí)行順序:
除了賦值運(yùn)算符和 null 合并運(yùn)算符之外,所有二元運(yùn)算符均為左結(jié)合運(yùn)算符,即從左向右執(zhí)行運(yùn)算。
例如,x + y + z
將計(jì)算為 (x + y) + z
。
賦值運(yùn)算符、null 合并 ?? 和 ??= 運(yùn)算符和條件運(yùn)算符 ?: 為右結(jié)合運(yùn)算符,即從右向左執(zhí)行運(yùn)算。 例如,x = y = z
將計(jì)算為 x = (y = z)。
可以使用括號控制優(yōu)先級和結(jié)合性。
例如,x + y * z
先計(jì)算 y 乘 z,并將結(jié)果與 x 相加,而 (x + y) * z 則先計(jì)算 x 加 y,然后將結(jié)果與 z 相乘。
大部分運(yùn)算符可 重載。 借助運(yùn)算符重載,可以為一個(gè)或兩個(gè)操作數(shù)為用戶定義類或結(jié)構(gòu)類型的運(yùn)算指定用戶定義運(yùn)算符實(shí)現(xiàn)代碼。
C# 提供了運(yùn)算符,用于執(zhí)行算術(shù)、邏輯、按位和移位運(yùn)算以及相等和排序比較。
7、語句
程序操作使用 語句 進(jìn)行表示。 C# 支持幾種不同的語句,其中許多語句是從嵌入語句的角度來定義的。
- 使用 代碼塊,可以在允許編寫一個(gè)語句的上下文中編寫多個(gè)語句。 代碼塊是由一系列在分隔符
{
和}
內(nèi)編寫的語句組成。 - 聲明語句 用于聲明局部變量和常量。
- 表達(dá)式語句 用于計(jì)算表達(dá)式。 可用作語句的表達(dá)式包括方法調(diào)用、使用 new 運(yùn)算符的對象分配、使用 = 和復(fù)合賦值運(yùn)算符的賦值、使用 ++ 和 -- 運(yùn)算符和 await 表達(dá)式的遞增和遞減運(yùn)算。
- 選擇語句 用于根據(jù)一些表達(dá)式的值從多個(gè)可能的語句中選擇一個(gè)以供執(zhí)行。 此組包含 if 和 switch 語句。
- 迭代語句 用于重復(fù)執(zhí)行嵌入語句。 此組包含 while、do、for 和 foreach 語句。
- 跳轉(zhuǎn)語句 用于轉(zhuǎn)移控制權(quán)。 此組包含
break
、continue
、goto
、throw
、return
和yield
語句。 - try...catch 語句用于捕獲在代碼塊執(zhí)行期間發(fā)生的異常,try...finally 語句用于指定始終執(zhí)行的最終代碼,無論異常發(fā)生與否。
-
checked
和unchecked
語句用于控制整型類型算術(shù)運(yùn)算和轉(zhuǎn)換的溢出檢查上下文。 - lock 語句用于獲取給定對象的相互排斥鎖定,執(zhí)行語句,然后解除鎖定。
- using 語句用于獲取資源,執(zhí)行語句,然后釋放資源。
下面列出了可使用的語句類型:
- 局部變量聲明。
- 局部常量聲明。
- 表達(dá)式語句。
- if 語句。
- switch 語句。
- while 語句。
- do 語句。
- for 語句。
- foreach 語句。
- break 語句。
- continue 語句。
- goto 語句。
- return 語句。
- yield 語句。
- throw 和 try 語句。
- checked 和 unchecked 語句。
- lock 語句。
- using 語句。
原文鏈接:https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/program-building-blocks
相關(guān)推薦
- 2022-10-26 一文解析?Golang?sync.Once?用法及原理_Golang
- 2023-07-24 uniapp開發(fā)小程序端原生導(dǎo)航欄
- 2022-07-06 python數(shù)據(jù)分析之DateFrame數(shù)據(jù)排序和排名方式_python
- 2022-03-20 C++線程池實(shí)現(xiàn)代碼_C 語言
- 2022-04-01 詳解Prometheus自動發(fā)現(xiàn)之file_sd_config
- 2022-09-10 詳解Python腳本如何設(shè)置試用期_python
- 2022-07-08 python基礎(chǔ)知識之索引與切片詳解_python
- 2022-07-03 如何讓Python在HTML中運(yùn)行_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支