转] C# 泛型类型参数的约束

简介:

啊.紫原文C# 泛型类型参数的约束

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。下表列出了六种类型的约束:

1
2
3
4
5
6
7
8
9
10
11
12
where  T:  struct
类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。有关更多信息,请参见使用可以为  null  的类型(C# 编程指南)。
where  T :  class
类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
where  T: new ()
类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时, new () 约束必须最后指定。
where  T:<基类名>
类型参数必须是指定的基类或派生自指定的基类。
where  T:<接口名称>
类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。
where  T:U
为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。约束是使用上下文关键字 where 应用的。

  View Code

约束使得泛型类能够使用 Employee.Name 属性,因为类型为 T 的所有项都保证是 Employee 对象或从 Employee 继承的对象。

可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型,如下所示:

 

1
2
3
4
class  EmployeeList<T>  where  T : Employee, IEmployee, System.IComparable<T>,  new ()
{
     // ...
}

 

通过约束类型参数,可以增加约束类型及其继承层次结构中的所有类型所支持的允许操作和方法调用的数量。因此,在设计泛型类或方法时,如果要对泛型成员执行除简单赋值之外的任何操作或调用 System.Object 不支持的任何方法,您将需要对该类型参数应用约束。

在应用 where T : class 约束时,避免对类型参数使用 == 和 != 运算符,因为这些运算符仅测试引用同一性而不测试值相等性。即使在用作参数的类型中重载这些运算符也是如此。下面的代码说明了这一点;即使 String 类重载 == 运算符,输出也为 false。

 

1
2
3
4
5
6
7
8
9
10
11
public  static  void  OpTest<T>(T s, T t)  where  T :  class
{
     System.Console.WriteLine(s == t);
}
static  void  Main()
{
     string  s1 =  "target" ;
     System.Text.StringBuilder sb =  new  System.Text.StringBuilder( "target" );
     string  s2 = sb.ToString();
     OpTest< string >(s1, s2);
}

 

这种情况的原因在于,编译器在编译时仅知道 T 是引用类型,因此必须使用对所有引用类型都有效的默认运算符。如果必须测试值相等性,建议的方法是同时应用 where T : IComparable<T> 约束,并在将用于构造泛型类的任何类中实现该接口。

 

约束多个参数

可以对多个参数应用约束,并对一个参数应用多个约束,如下面的示例所示:

1
2
3
4
class  Base { }
class  Test<T, U>
     where  U :  struct
     where  T : Base,  new () { }

未绑定的类型参数

没有约束的类型参数(如公共类 SampleClass<T>{} 中的 T)称为未绑定的类型参数。未绑定的类型参数具有以下规则:

不能使用 != 和 == 运算符,因为无法保证具体类型参数能支持这些运算符。

可以在它们与 System.Object 之间来回转换,或将它们显式转换为任何接口类型。

可以将它们与 null 进行比较。将未绑定的参数与 null 进行比较时,如果类型参数为值类型,则该比较将始终返回 false。

作为约束的类型参数

将泛型类型参数作为约束使用,在具有自己类型参数的成员函数必须将该参数约束为包含类型的类型参数时非常有用,如下示例所示:

1
2
3
4
class  List<T>
{
     void  Add<U>(List<U> items)  where  U : T { /*...*/ }
}

在上面的示例中,T 在 Add 方法的上下文中是一个类型约束,而在 List 类的上下文中是一个未绑定的类型参数。

类型参数还可在泛型类定义中用作约束。请注意,必须在尖括号中声明此类型参数与任何其他类型的参数:

1
2
//Type parameter V is used as a type constraint.
public  class  SampleClass<T, U, V>  where  T : V { }

 

泛型类的类型参数约束的作用非常有限,因为编译器除了假设类型参数派生自 System.Object 以外,不会做其他任何假设。在希望强制两个类型参数之间的继承关系的情况下,可对泛型类使用参数类型约束。

 

 

 

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。




    本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5868820.html,如需转载请自行联系原作者


相关文章
|
11月前
|
JSON C# 数据格式
【Azure Function】C#独立工作模式下参数类型 ServiceBusReceivedMessage 无法正常工作
Cannot convert input parameter 'message' to type 'Azure.Messaging.ServiceBus.ServiceBusReceivedMessage' from type 'System.String'.
220 73
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
167 3
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
278 2
C# 可空类型(Nullable)
C# 单问号 ? 与 双问号 ??
200 12
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
236 11
|
编译器 C#
c# - 运算符<<不能应用于long和long类型的操作数
在C#中,左移运算符的第二个操作数必须是 `int`类型,因此需要将 `long`类型的位移计数显式转换为 `int`类型。这种转换需要注意数据丢失和负值处理的问题。通过本文的详细说明和示例代码,相信可以帮助你在实际开发中正确使用左移运算符。
172 0
|
编译器 C#
C#中内置的泛型委托Func与Action
C#中内置的泛型委托Func与Action
248 4
|
开发框架 .NET 编译器
C# 中的记录(record)类型和类(class)类型对比总结
C# 中的记录(record)类型和类(class)类型对比总结
403 0
|
传感器 开发框架 JSON
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
634 0
|
3月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
192 19

热门文章

最新文章