C#类型参数约束分析及应用浅析

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

十载的隆林网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都全网营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整隆林建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“隆林网站设计”,“隆林网站推广”以来,每个客户项目都认真落实执行。

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

◆T:结构

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。

◆T:类

类型参数必须是引用类型,包括任何类、接口、委托或数组类型。

◆T:new()

类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须***指定。

◆T:<基类名>

类型参数必须是指定的基类或派生自指定的基类。

◆T:<接口名称>

类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

◆T:U

为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。

C# 类型参数约束代码

 
 
 
  1. public class Employee  
  2. {  
  3.     private string name;  
  4.     private int id;  
  5.  
  6.     public Employee(string s, int i)  
  7.     {  
  8.         name = s;  
  9.         id = i;  
  10.     }  
  11.  
  12.     public string Name  
  13.     {  
  14.         get { return name; }  
  15.         set { name = value; }  
  16.     }  
  17.  
  18.     public int ID  
  19.     {  
  20.         get { return id; }  
  21.         set { id = value; }  
  22.     }  
  23. }  
  24.  
  25. public class GenericList  where T : Employee  
  26. {  
  27.     private class Node  
  28.     {  
  29.         private Node next;  
  30.         private T data;  
  31.  
  32.         public Node(T t)  
  33.         {  
  34.             next = null;  
  35.             data = t;  
  36.         }  
  37.  
  38.         public Node Next  
  39.         {  
  40.             get { return next; }  
  41.             set { next = value; }  
  42.         }  
  43.  
  44.         public T Data  
  45.         {  
  46.             get { return data; }  
  47.             set { data = value; }  
  48.         }  
  49.     }  
  50.  
  51.     private Node head;  
  52.  
  53.     public GenericList() //constructor  
  54.     {  
  55.         head = null;  
  56.     }  
  57.  
  58.     public void AddHead(T t)  
  59.     {  
  60.         Node n = new Node(t);  
  61.         n.Next = head;  
  62.         head = n;  
  63.     }  
  64.  
  65.     public IEnumerator  GetEnumerator()  
  66.     {  
  67.         Node current = head;  
  68.  
  69.         while (current != null)  
  70.         {  
  71.             yield return current.Data;  
  72.             current = current.Next;  
  73.         }  
  74.     }  
  75.  
  76.     public T FindFirstOccurrence(string s)  
  77.     {  
  78.         Node current = head;  
  79.         T t = null;  
  80.  
  81.         while (current != null)  
  82.         {  
  83.             //The constraint enables access to the Name property.  
  84.             if (current.Data.Name == s)  
  85.             {  
  86.                 t = current.Data;  
  87.                 break;  
  88.             }  
  89.             else 
  90.             {  
  91.                 current = current.Next;  
  92.             }  
  93.         }  
  94.         return t;  
  95.     }  

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

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

C# 类型参数约束代码

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

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

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

C# 类型参数约束代码

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

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

C# 未绑定的类型参数

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

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

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

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

C# 裸类型约束

用作约束的泛型类型参数称为裸类型约束。当具有自己的类型参数的成员函数需要将该参数约束为包含类型的类型参数时,裸类型约束很有用,如下面的示例所示:

C# 类型参数约束代码

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

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

裸类型约束还可以在泛型类定义中使用。注意,还必须已经和其他任何类型参数一起在尖括号中声明了裸类型约束:

C# 类型参数约束代码

 
 
 
  1. //naked type constraint  
  2. public class SampleClass  where T : V { } 

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

C# 类型参数约束的相关内容就向你介绍到这里,希望对你了解和学习C# 类型参数约束有所帮助。

分享名称:C#类型参数约束分析及应用浅析
网页地址:http://www.gawzjz.com/qtweb/news49/162999.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联