Visual Studio 2005
其他版本
在定义泛型类时,能够对客户端代码能够在实例化类时用于范例参数的范例品种施加限定。假如客户端代码尝试运用某个束缚所不许可的范例来实例化类,则会发生编译时毛病。这些限定称为束缚。束缚是运用 where 高低文关键字指定的。下表列出了六种范例的束缚:
束缚 | 申明 |
---|---|
T:组织 |
范例参数必需是值范例。能够指定除 Nullable 以外的任何值范例。有关更多信息,请拜见运用可空范例(C# 编程指南)。 |
T:类 |
范例参数必需是援用范例,包括任何类、接口、托付或数组范例。 |
T:new() |
范例参数必需具有没有参数的大众组织函数。当与其他束缚一同运用时,new() 束缚必需末了指定。 |
T:<基类名> |
范例参数必需是指定的基类或派生自指定的基类。 |
T:<接口称号> |
范例参数必需是指定的接口或完成指定的接口。能够指定多个接口束缚。束缚接口也能够是泛型的。 |
T:U |
为 T 供应的范例参数必需是为 U 供应的参数或派生自为 U 供应的参数。这称为裸范例束缚。 |
运用束缚的缘由
假如要搜检泛型列表中的某个项以肯定它是不是有效,或许将它与其他某个项举行比较,则编译器必需在肯定程度上保证它须要挪用的运算符或要领将遭到客户端代码能够指定的任何范例参数的支撑。这类保证是经由过程对泛型类定义运用一个或多个束缚取得的。比方,基类束缚通知编译器:仅此范例的对象或今后范例派生的对象才可用作范例参数。一旦编译器有了这个保证,它就能够许可在泛型类中挪用该范例的要领。束缚是运用高低文关键字 where 运用的。下面的代码示例演示可经由过程运用基类束缚添加到 GenericList<T> 类(在泛型引见(C# 编程指南)中)的功用。
public class Employee { private string name; private int id; public Employee(string s, int i) { name = s; id = i; } public string Name { get { return name; } set { name = value; } } public int ID { get { return id; } set { id = value; } } } public class GenericList<T> where T : Employee { private class Node { private Node next; private T data; public Node(T t) { next = null; data = t; } public Node Next { get { return next; } set { next = value; } } public T Data { get { return data; } set { data = value; } } } private Node head; public GenericList() //constructor { head = null; } public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } } public T FindFirstOccurrence(string s) { Node current = head; T t = null; while (current != null) { //The constraint enables access to the Name property. if (current.Data.Name == s) { t = current.Data; break; } else { current = current.Next; } } return t; } }
经由过程束缚范例参数,能够增添束缚范例及其继续条理组织中的一切范例所支撑的许可操纵和要领挪用的数目。因而,在设想泛型类或要领时,假如要对泛型成员实行除简朴赋值以外的任何操纵或挪用 System.Object 不支撑的任何要领,您将须要对该范例参数运用束缚。
在运用 where T : class 束缚时,发起不要对范例参数运用 == 和 != 运算符,由于这些运算符仅测试援用同一性而不测试值相称性。纵然在用作参数的范例中重载这些运算符也是云云。下面的代码申清楚明了这一点;纵然 String 类重载 == 运算符,输出也为 false。
C#
public static void OpTest<T>(T s, T t) where T : class { System.Console.WriteLine(s == t); } static void Main() { string s1 = "foo"; System.Text.StringBuilder sb = new System.Text.StringBuilder("foo"); string s2 = sb.ToString(); OpTest<string>(s1, s2); }
这类状况的缘由在于,编译器在编译时仅晓得 T 是援用范例,因而必需运用对一切援用范例都有效的默许运算符。假如须要测试值相称性,发起的要领是同时运用 where T : IComparable<T> 束缚,并在将用于组织泛型类的任何类中完成该接口。
未绑定的范例参数
没有束缚的范例参数(如大众类 SampleClass<T>{} 中的 T)称为未绑定的范例参数。未绑定的范例参数具有以下划定规矩:
不能运用 != 和 == 运算符,由于没法保证详细范例参数能支撑这些运算符。
能够在它们与 System.Object 之间往返转换,或将它们显式转换为任何接口范例。
能够将它们与 null 举行比较。将未绑定的参数与 null 举行比较时,假如范例参数为值范例,则该比较将一直返回 false。
裸范例束缚
用作束缚的泛型范例参数称为裸范例束缚。当具有本身的范例参数的成员函数须要将该参数束缚为包括范例的范例参数时,裸范例束缚很有效,以下面的示例所示:
C#
class List<T> { void Add<U>(List<U> items) where U : T {/*...*/} }
在上面的示例中,T 在 Add 要领的高低文中是一个裸范例束缚,而在 List 类的高低文中是一个未绑定的范例参数。
裸范例束缚还能够在泛型类定义中运用。注重,还必需已和其他任何范例参数一同在尖括号中声清楚明了裸范例束缚:
C# //naked type constraint public class SampleClass<T, U, V> where T : V { }
泛型类的裸范例束缚的作用异常有限,由于编译器除了假定某个裸范例束缚派生自 System.Object 以外,不会做其他任何假定。在愿望强迫两个范例参数之间的继续关联的状况下,可对泛型类运用裸范例束缚。
以上就是C# 中where范例束缚的图文概况引见的内容,更多相关内容请关注ki4网(www.ki4.cn)!