当前位置: 首页 > article >正文

windows C#-泛型类型参数的约束详解(一)

使用约束的原因

约束指定类型参数的功能和预期。 声明这些约束意味着你可以使用约束类型的操作和方法调用。 如果泛型类或方法对泛型成员使用除简单赋值之外的任何操作,包括调用 System.Object 不支持的任何方法,则对类型参数应用约束。 例如,基类约束告诉编译器,只有此类型的对象或派生自此类型的对象可替换该类型参数。 编译器有了此保证后,就能够允许在泛型类中调用该类型的方法。 以下代码示例演示可通过应用基类约束添加到(泛型介绍中的)GenericList<T> 类的功能。

public class Employee
{
    public Employee(string name, int id) => (Name, ID) = (name, id);
    public string Name { get; set; }
    public int ID { get; set; }
}

public class GenericList<T> where T : Employee
{
    private class Node
    {
        public Node(T t) => (Next, Data) = (null, t);

        public Node? Next { get; set; }
        public T Data { get; set; }
    }

    private Node? head;

    public void AddHead(T t)
    {
        Node n = new Node(t) { 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 继承的对象。

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

class EmployeeList<T> where T : notnull, Employee, IComparable<T>, new()
{
    // ...
    public void AddDefault()
    {
        T t = new T();
        // ...
    }
}

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

public static void OpEqualsTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}

private static void TestStringEquality()
{
    string s1 = "target";
    System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
    string s2 = sb.ToString();
    OpEqualsTest<string>(s1, s2);
}

 

编译器只知道 T 在编译时是引用类型,并且必须使用对所有引用类型都有效的默认运算符。 如果必须测试值相等性,请应用 where T : IEquatable<T> 或 where T : IComparable<T> 约束,并在用于构造泛型类的任何类中实现该接口。

约束多个参数

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

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

 


http://www.kler.cn/a/488448.html

相关文章:

  • 左值引用(Lvalue Reference)和右值引用(Rvalue Reference)详解
  • <rust>在rust中,实现32位浮点数与16进制之间的转换
  • 搭建docker私有化仓库Harbor
  • 2024年华为OD机试真题-判断一组不等式是否满足约束并输出最大差-Python-OD统一考试(E卷)
  • EtherCAT转Modbus网关与TwinCAT3的连接及配置详述
  • Leecode刷题C语言之字符串中最大的3位相同数字
  • 算法-盒子中小球的最大数量
  • C16.【C++ Cont】string类字符串的关系运算和与string有关的函数
  • JavaScript系列(10)-- Map数据结构专题
  • 如何确保获取的淘宝详情页数据的准确性和时效性?
  • 基于Ubuntu2404脚本搭建openstackC版-ovn网络驱动
  • 设计模式 创建型 抽象工厂模式(Abstract Factory)与 常见技术框架应用 解析
  • Win32汇编学习笔记06.APIHook
  • 单片机 期末笔记
  • 《探秘鸿蒙NEXT中的人工智能核心架构》
  • 【2025 Rust学习 --- 11 实用工具特型01】
  • 车载音频开发(二):对音频数据作音量调节
  • Java 基于微信小程序的高校科研团队管理系统设计与实现(附源码,部署,文档
  • PHP RCE
  • JS爬虫实战演练
  • js观察者模式
  • nginx反向代理和负载均衡的区别
  • 【LeetCode】303. 区域和检索 - 数组不可变
  • linux 设置mysql 外网访问
  • 微信原生小程序自定义封装组件(以导航navbar为例)
  • 1.3作业