正在阅读:C# 最强大的功能--泛型简介C# 最强大的功能--泛型简介

2005-06-23 10:16 出处: 作者:Juval Lowy 责任编辑:moningfeng

当客户端使用该链表时,该客户端必须提供类型实参。该客户端可以选择整数作为键,并且选择字符串作为数据项:

LinkedList list = new LinkedList();
list.AddHead(123,"AAA");



但是,该客户端可以选择其他任何组合(例如,时间戳)来表示键:

LinkedList list = new LinkedList();
list.AddHead(DateTime.Now,"AAA");



有时,为特定类型的特殊组合起别名是有用的。可以通过 using 语句完成该操作,如代码块 4 中所示。请注意,别名的作用范围是文件的作用范围,因此您必须按照与使用 using 命名空间相同的方式,在项目文件中反复起别名。

代码块 4. 一般类型别名

using List = LinkedList;

class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123,"AAA");
}
}




一般约束
使用 C# 泛型,编译器会将一般代码编译为 IL,而不管客户端将使用什么样的类型实参。因此,一般代码可以尝试使用与客户端使用的特定类型实参不兼容的一般类型参数的方法、属性或成员。这是不可接受的,因为它相当于缺少类型安全。在 C# 中,您需要通知编译器客户端指定的类型必须遵守哪些约束,以便使它们能够取代一般类型参数而得到使用。存在三个类型的约束。派生约束指示编译器一般类型参数派生自诸如接口或特定基类之类的基类型。默认构造函数约束指示编译器一般类型参数公开了默认的公共构造函数(不带任何参数的公共构造函数)。引用/值类型约束将一般类型参数约束为引用类型或值类型。一般类型可以利用多个约束,您甚至可以在使用一般类型参数时使 IntelliSense 反射这些约束,例如,建议基类型中的方法或成员。

需要注意的是,尽管约束是可选的,但它们在开发一般类型时通常是必不可少的。没有它们,编译器将采取更为保守的类型安全方法,并且只允许在一般类型参数中访问 Object 级别功能。约束是一般类型元数据的一部分,以便客户端编译器也可以利用它们。客户端编译器只允许客户端开发人员使用遵守这些约束的类型,从而实施类型安全。

以下示例将详细说明约束的需要和用法。假设您要向代码块 3 的链表中添加索引功能或按键搜索功能:

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;
}


键盘也能翻页,试试“← →”键

关注我们

最新资讯离线随时看 聊天吐槽赢奖品