美文网首页
类型参数的约束(C# 编程指南)

类型参数的约束(C# 编程指南)

作者: ShingKwan | 来源:发表于2017-10-13 16:34 被阅读0次

约束说明

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

约束 描述
where T:结构 类型参数必须是值类型。 可以指定除 Nullable 以外的任何值类型。 有关详细信息,请参阅使用可以为 null 的类型
where T:类 类型参数必须是引用类型;这同样适用于所有类、接口、委托或数组类型。
where T:new() 类型参数必须具有公共无参数构造函数。 与其他约束一起使用时,new() 约束必须最后指定。
where T:<基类名称> 类型参数必须是指定的基类或派生自指定的基类。
where T:<接口名称> 类型参数必须是指定的接口或实现指定的接口。 可指定多个接口约束。 约束接口也可以是泛型。
where T:U 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

使用约束的原因

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

public class Employee
{
    private string name;
    private int id;

    public Employee(string s, int i)
    {
        name = s;
        id = i;
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int ID
    {
        get { return id; }
        set { id = value; }
    }
}

public class GenericList<T> where T : Employee
{
    private class Node
    {
        private Node next;
        private T data;

        public Node(T t)
        {
            next = null;
            data = t;
        }

        public Node Next
        {
            get { return next; }
            set { next = value; }
        }

        public T Data
        {
            get { return data; }
            set { data = value; }
        }
    }

    private Node head;

    public GenericList() //constructor
    {
        head = null;
    }

    public void AddHead(T t)
    {
        Node n = new Node(t);
        n.Next = head;
        head = n;
    }

    public IEnumerator<T> GetEnumerator()
    {
        Node current = head;

        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }

    public T FindFirstOccurrence(string s)
    {
        Node current = head;
        T t = null;

        while (current != null)
        {
            //The constraint enables access to the Name property.
            if (current.Data.Name == s)
            {
                t = current.Data;
                break;
            }
            else
            {
                current = current.Next;
            }
        }
        return t;
    }
}

约束使得泛型类能够使用 Employee.Name 属性,因为类型 T 的所有项都保证是 Employee 对象或是从 Employee 继承的对象。
可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型,如下所示:

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>约束,并在将用于构造泛型类的任何类中实现该接口。

约束多个参数

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

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

未绑定的类型参数

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

  • 不能使用 != 和 == 运算符,因为无法保证具体的类型参数能支持这些运算符。
  • 可以在它们与 System.Object 之间来回转换,或将它们显式转换为任何接口类型。
  • 可以将它们与 null 进行比较。 将未绑定的参数与 null 进行比较时,如果类型参数为值类型,则该比较将始终返回 false。

类型参数作为约束

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

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

在上述示例中,T 在 Add 方法的上下文中是一个类型约束,而在 List 类的上下文中是一个未绑定的类型参。
类型参数还可在泛型类定义中用作约束。 请注意,必须在尖括号中声明此类型参数以及任何其他类型参数:

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

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

相关文章

  • 类型参数的约束(C# 编程指南)

    约束说明 定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的几种类型施加限制。 如果客户端代码尝试使用约...

  • C# where用法

    C# where用法 where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量。1.接口约...

  • 引用类型的参数加不加Ref的区别

    问题描述:引用类型的参数加不加Ref的区别? 解答 备注:C#高级编程(第10版) 3.6.1 ref参数(92页...

  • Ts 进阶使用指南

    # Ts 使用指南 ## 6、参数类型和返回类型 ```ts // 参数类型和返回类型 function crea...

  • Swift 5.x 为泛型定义要求

    如类型约束中描述的一样, 类型约束允许你在泛型函数或泛型类型相关的类型形式参数上定义要求. 类型约束在为关联类型定...

  • C#参数类型

    一、按值参数传递 默认情况下C#中的参数默认按值传递,这是常用的方式。这意味着在将参数值传递给方法时将创建一份参数...

  • PHP7——及以上版本新特性简析

    指定参数类型(7以前就有)、可变参数个数、返回类型: 参数类型约束 以前版本的PHP,函数和类方法不需要声明变量类...

  • scala 类型参数、界定、类型约束

    类、特质、方法和函数都可以有类型参数 将类型参数放置在名称之后,以方括号括起来 参数类型(不能什么都传,要加限定)...

  • C#与C++类型互转

    一、C#调用DLL文件时参数对应表 二、C#调用C++编写的DLL函数, 以及各种类型的参数传递 如果函数只有传入...

  • swift-- 泛型

    类型约束 在⼀个类型参数后⾯放置协议或者是类,⽐如就要求我们的类型参数 T 遵循 Equatable 协议 关联类...

网友评论

      本文标题:类型参数的约束(C# 编程指南)

      本文链接:https://www.haomeiwen.com/subject/xxbzyxtx.html