C#2.0 泛型约束
点击次数:60 次 发布日期:2008-11-06 07:52:13 作者:源代码网
|
3.1为什么要泛型约束 看以下示例: public class LinkedList<K, T> { T Find(K key) public T this[K key] { get {return Find(key);} } } LinkedList<int, string> list = new LinkedList<int, string>(); list.AddHead(123,"AAA"); list.AddHead(456,"BBB"); string item=list[456]; Debug.Assert(item=="BBB"); Find方法实现: T Find(K key) { Node<K,T> current = m_Head; while(current.NextNode !=null) { //因为编译器不知道 K(实例化时的实际类型)是否支持==运算符,例如,默认情况下,结构不提供这样的实现 if (current.Key==key) //Will not compile break ; else current =current .NextNode ; } return current.Item ; } Find方法的解决方法 ---泛型增加一个派生约束(Derivation Constraints) //where 关键字 //K:IComparable表示K只接受实现IComparable接口的类型 public class LinkedList<K, T> where K:IComparable { T Find(K key) { Node<K,T> current = m_Head; while(current.NextNode !=null) { if (current.Key.CompareTo(key)==0) break ; else current =current.NextNode ; } return current.Item ; //Rest of the implementation } } 3.2 在C#2.0中,所有的派生约束必须放在类的实际派生列表之后,如: public class LinkedList<K, T>:IEnumerable<T> where K:IComparable {……} 3.3 通常,只需在需要的级别定一约束。比如:在Node节点定义IComparable<K>约束是没有意义的。如果一定要在Node上定义IComparable<K>约束,则LinkedList上也要定义约束。 class Node<K,T>where K:ICloneable <K> {……} public class LinkedList<KeyType,DataType> where KeyType:IConvertible <KeyType> { Node<KeyType ,DataType> m_Head; } 3.4 一个泛型参数撒谎能够约束多个接口(彼此用逗号分隔) public class LinkedList<K, T> where K : IComparable<K>, IConvertible { ......} 3.5 在一个约束中最多只能使用一个基类,这是因为C#不支持实现的多重继承 约束的基类不能是密封类或静态类,并且有编译器实施这一限制 不能将System.Delegate或System.Arry约束为基类 可以同时约束一个基类以及一个火多个接口,但是该基类必须首先出现在派生约束列表中 public class LinkedList<K, T> where K :MyBaseClass ,IComparable<K> { ......} 3.5 在一个约束中最多只能使用一个基类,这是因为C#不支持实现的多重继承 约束的基类不能是密封类或静态类,并且有编译器实施这一限制 不能将System.Delegate或System.Arry约束为基类 可以同时约束一个基类以及一个火多个接口,但是该基类必须首先出现在派生约束列表中 public class LinkedList<K, T> where K :MyBaseClass ,IComparable<K> { ......} 3.6 自定义的接口或基类必须与泛型参数具有一致的可见性 即: 正确的可见性 public class MyBaseClass { } internal class MySubClass<T> where:MyBaseClass {} 颠倒的可见性 internal class MyBaseClass { } public class MySubClass<T> where:MyBaseClass {} 3.7泛型约束—构造函数约束 ·假设你要在一般类的内部实例化一个新的一般对象。问题在于,C#编译器不知道客户端将使用的类型参数是否具有匹配的构造函数,因而它将拒绝编译实例化行。 ·为了解决该问题,C#允许约束一般类型参数,以使其必须支持公共默认构造函数。这是使用new()约束完成的。 public Node<K,T>where T:new() { public K Key; public T item; public Node<K,T>NextNode; public Node() { Key =default(K); item=new T(); NextNode=null; } } ·可以将构造函数约束与派生约束组合起来,前提是构造函数约束出现在约束列表中的最后 public class LinkedList<K, T> where K : IComparable<K>, new() { ......} 3.8 泛型约束----引用/值类型约束 · 可以使用struct约束将一般类型参数约束为值类型(例如,int 、bool和enum),或任何自定义结构 public class MyClass <T>where T:struct {…… } · 同样,可以使用Class约束将一般类型参数约束为引用类型(类) public class MyClass <T>where T:class {…… } ·不能将引用/值类型约束与基类约束一起使用,因为基类约束涉及到类 ·不能使用结构和默认构造函数约束,因为默认构造函数约束也涉及到类 ·虽然可以使用类和默认构造函数约束,但这样做并没有任何价值 ·可以将引用/值类型约束与接口与约束组合起来,前提是引用/值类型约束出现在约束列表的开头 源代码网推荐 源代码网供稿. |
