C# 泛型约束中的一般约束使用 C# 泛型,编译器会将一般代码编译为 IL,而不管客户端将使用什么样的类型实参。因此,一般代码可以尝试使用与客户端使用的特定类型实参不兼容的一般类型参数的方法、属性或成员。这是不可接受的,因为它相当于缺少类型安全。在 C# 中,您需要通知编译器客户端指定的类型必须遵守哪些约束,以便使它们能够取代一般类型参数而得到使用。存在三个类型的约束。派生约束指示编译器一般类型参数派生自诸如接口或特定基类之类的基类型。默认构造函数约束指示编译器一般类型参数公开了默认的公共构造函数(不带任何参数的公共构造函数)。引用/值类型约束将一般类型参数约束为引用类型或值类型。一般类型可以利用多个约束,您甚至可以在使用一般类型参数时使 IntelliSense 反射这些约束,例如,建议基类型中的方法或成员。
需要注意的是,尽管C# 泛型约束是可选的,但它们在开发一般类型时通常是必不可少的。没有它们,编译器将采取更为保守的类型安全方法,并且只允许在一般类型参数中访问 Object 级别功能。约束是一般类型元数据的一部分,以便客户端编译器也可以利用它们。客户端编译器只允许客户端开发人员使用遵守这些约束的类型,从而实施类型安全。
C# 泛型约束中的一般约束应用实例:
以下示例将详细说明C# 泛型约束的需要和用法。假设您要链表中添加索引功能或按键搜索功能
- public class LinkedList
- {
- T Find(K key)
- {...}
- public T this[K key]
- {
- get{return Find(key);}
- }
- }
这使客户端可以编写以下代码:
- LinkedList list = new LinkedList();
- list.AddHead(123,"AAA");
- list.AddHead(456,"BBB");
- string item = list[456];
- Debug.Assert(item == "BBB");
要实现搜索,您需要扫描列表,将每个节点的键与您要查找的键进行比较,并且返回键匹配的节点的项。问题在于,Find() 的以下实现无法编译:
- T Find(K key)
- {
- Node current = m_Head;
- while(current.NextNode != null)
- {
- if(current.Key == key) //Will not compile
- break;
- else
- current = current.NextNode;
- }
- return current.Item;
- }
原因在于,编译器将拒绝编译以下行:
- if(current.Key == key)
上述行将无法编译,因为编译器不知道 K(或客户端提供的实际类型)是否支持 == 运算符。例如,默认情况下,结构不提供这样的实现。您可以尝试通过使用 IComparable 接口来克服 == 运算符局限性:
- public interface IComparable
- {
- int CompareTo(object obj);
- }
如果您与之进行比较的对象等于实现该接口的对象,则 CompareTo() 返回 0;因此,Find() 方法可以按如下方式使用它:
- if(current.Key.CompareTo(key) == 0)
遗憾的是,这也无法编译,因为编译器无法知道 K(或客户端提供的实际类型)是否派生自 IComparable。
您可以显式强制转换到 IComparable,以强迫编译器编译比较行,除非这样做需要牺牲类型安全:
- if(((IComparable)(current.Key)).CompareTo(key) == 0)
如果客户端使用的类型不是派生自 IComparable,则会导致运行时异常。此外,当所使用的键类型是值类型而非键类型参数时,您可以对该键执行装箱,而这可能具有一些性能方面的影响。
C# 泛型约束中的一般约束相关的内容就向你介绍到这里,希望对你了解和学习C# 泛型约束中的一般约束有所帮助。
【编辑推荐】