在定義泛型類時,可以對客戶端**能夠在例項化類時用於型別引數的型別種類施加限制。如果客戶端**嘗試使用某個約束所不允許的型別來例項化類,則會產生編譯時錯誤。這些限制稱為約束。約束是使用 where 上下文關鍵字指定的。下表列出了六種型別的約束:
約束說明
t:結構
型別引數必須是值型別。可以指定除 nullable 以外的任何值型別。有關更多資訊,請參見使用可空型別(c# 程式設計指南)。
t:類型別引數必須是引用型別,包括任何類、介面、委託或陣列型別。
t:new()
型別引數必須具有無引數的公共建構函式。當與其他約束一起使用時,new()約束必須最後指定。
t:《基類名》
型別引數必須是指定的基類或派生自指定的基類。
t:《介面名稱》
型別引數必須是指定的介面或實現指定的介面。可以指定多個介面約束。約束介面也可以是泛型的。
t:u為 t 提供的型別引數必須是為 u 提供的引數或派生自為 u 提供的引數。這稱為裸型別約束。
如果要檢查泛型列表中的某個項以確定它是否有效,或者將它與其他某個項進行比較,則編譯器必須在一定程度上保證它需要呼叫的運算子或方法將受到客戶端**可能指定的任何型別引數的支援。這種保證是通過對泛型類定義應用乙個或多個約束獲得的。例如,基類約束告訴編譯器:僅此型別的物件或從此型別派生的物件才可用作型別引數。一旦編譯器有了這個保證,它就能夠允許在泛型類中呼叫該型別的方法。約束是使用上下文關鍵字where應用的。下面的**示例演示可通過應用基類約束新增到 genericlist類(在泛型介紹(c# 程式設計指南)中)的功能。c#
publicclass employee
public
string name
set
}public
int id
set
}}public
class genericlistwhere t : employee
public node next
set
}public t data
set }}
private node head;
public genericlist() //constructor
public
void addhead(t t)
public ienumeratorgetenumerator()
}public t findfirstoccurrence(string s)
else
}return t;
}}
約束使得泛型類能夠使用 employee.name 屬性,因為型別為 t 的所有項都保證是 employee 物件或從 employee 繼承的物件。
可以對同一型別引數應用多個約束,並且約束自身可以是泛型型別,如下所示:c#
class employeelistwhere t : employee, iemployee, system.icomparable, new()
通過約束型別引數,可以增加約束型別及其繼承層次結構中的所有型別所支援的允許操作和方法呼叫的數量。因此,在設計泛型類或方法時,如果要對泛型成員執行除簡單賦值之外的任何操作或呼叫system.object不支援的任何方法,您將需要對該型別引數應用約束。
在應用 where t : class 約束時,建議不要對型別引數使用==和!=運算子,因為這些運算子僅測試引用同一性而不測試值相等性。即使在用作引數的型別中過載這些運算子也是如此。下面的**說明了這一點;即使 string 類過載==運算子,輸出也為 false。c#
publicstatic
void optest(t s, t t) where t : class
static
void main()
這種情況的原因在於,編譯器在編譯時僅知道 t 是引用型別,因此必須使用對所有引用型別都有效的預設運算子。如果需要測試值相等性,建議的方法是同時應用 where t : icomparable 約束,並在將用於構造泛型類的任何類中實現該介面。
沒有約束的型別引數(如公共類 sampleclass{} 中的 t)稱為未繫結的型別引數。未繫結的型別引數具有以下規則:
用作約束的泛型型別引數稱為裸型別約束。當具有自己的型別引數的成員函式需要將該引數約束為包含型別的型別引數時,裸型別約束很有用,如下面的示例所示:c#
class list}
在上面的示例中,t 在add方法的上下文中是乙個裸型別約束,而在list類的上下文中是乙個未繫結的型別引數。
裸型別約束還可以在泛型類定義中使用。注意,還必須已經和其他任何型別引數一起在尖括號中宣告了裸型別約束:c#
//naked type constraintpublic
class sampleclasswhere t : v
泛型類的裸型別約束的作用非常有限,因為編譯器除了假設某個裸型別約束派生自system.object以外,不會做其他任何假設。在希望強制兩個型別引數之間的繼承關係的情況下,可對泛型類使用裸型別約束。
載自msdn
(v=vs.80).aspx
型別引數的約束(C 程式設計指南)
約束告知編譯器型別引數必須具備的功能。在沒有任何約束的情況下,型別引數可以是任何型別。編譯器只能假定 object 的成員,它是任何 net 型別的最終基類。有關詳細資訊,請參閱使用約束的原因。如果客戶端 嘗試使用約束所不允許的型別來例項化類,則會產生編譯時錯誤。通過使用where上下文關鍵字指定約...
C 型別引數的約束
在定義泛型類時,可以對客戶端 能夠在例項化類時用於型別引數的型別種類施加限制。如果客戶端 嘗試使用某個約束所不允許的型別來例項化類,則會產生編譯時錯誤。這些限制稱為約束。約束是使用where上下文關鍵字指定的。下表列出了六種型別的約束 約束 說明 t 結構 型別引數必須是值型別。可以指定除 null...
傳遞引用型別引數(C 程式設計指南)
引用型別的變數不直接包含其資料 它包含的是對其資料的引用。當通過值傳遞引用型別的引數時,有可能更改引用所指向的資料,如某類成員的值。但是無法更改引用本身的值 也就是說,不能使用相同的引用為新類分配記憶體並使之在塊外保持。若要這樣做,應使用 ref 或 out 關鍵字傳遞引數。為了簡單起見,下面的示例...