C# 中使用泛型约束来限制类型参数范围

定义泛型类型时,可以指定一个或者多个约束来限制泛型参数的范围。在实例化一个泛型类型时,若提供的类型不满足约束要求,编译器就会报错。

new() 约束

new 约束要求类型参数必须有公共无参数构造函数,与其它约束一起使用时,new() 约束必须放在最后。因为值类型都具有默认的公共无参构造函数,所以所有的值类型都满足 new() 约束。

class DataStore where T : new() { public T Data { get; set; } } // int 是值类型,满足约束 var store = new DataStore();

struct 约束

struct 约束要求类型参数只能是非空值类型,struct 类型不能和 new() 同时使用,原因前面已经说过,即所有的值类型自动满足 new() 约束。

class DataStore where T : struct { public T Data { get; set; } } // 报错,因为 string 是引用类型 var store = new DataStore(); // 报错,因为是可空值类型 var store = new DataStore(); //正确,int 是值类型 var store = new DataStore();

class 和 class?约束

class 约束要求类型参数只能是引用类型,比如类、接口、委托、数组。在 C# 8.0 即以后,若打开了 nullable 开关,则必须是不可空引用类型。

class DataStore where T : class { public T Data { get; set; } = default!; } // 报错,int 不是引用类型 var store = new DataStore(); // 在C#8.0以上打开 nullable 开关后报错 // 因为是可空的 var store = new DataStore(); // 正确,string 是不可空引用类型 var store = new DataStore();

class? 约束和 class 类似,都要求类型参数必须是引用类型,但对是否是 nullable 没有要求。

class DataStore where T : class? { public T Data { get; set; } } // 正确,无论可空或者不可空的引用类型都可以 var store = new DataStore(); // 正确,无论可空或者不可空的引用类型都可以 var store = new DataStore();

基类约束和接口约束

BaseClass 约束要求类型参数必须是指定的基类或者派生自指定的基类。在 C# 8.0 即以后,若打开了 nullable 开关,则必须是不可空的,BaseClass? 则对可空性不做要求,既可以为不可空的,也可以为可空的。

public class Person { public string Name { get; set; } = string.Empty; } public class Student : Person { public int Score { get; set; } } class DataStore where T : Person { public T Data { get; set; } = default!; } // 错误,Person? 为可空类型 // 如需适用可空类型,使用 where T : Person? 约束 var store = new DataStore(); // 正确,Student 派生自 Person var store = new DataStore();

此外,还有类似的 Interface 和 Interface? 约束,即类型参数必须实现指定的接口。在 C# 8.0 及以后版本,若打开了 nullable 开关,类型参数必须不可空,Interface? 则不做要求

class DataStore where T : IComparable { public T Data { get; set; } = default!; }

类型参数作为约束

where T : U 约束要求类型参数 T 必须是 U 或者 U的子类型。开启了 nullable 开关后,两者的可空性必须相同。

public class List { public void Add(List items) where U : T }

notnull约束

C# 8.0 引入了 notnull 约束, 要求类型参数必须非空,既可以是非空值类型,也可以是非空引用类型。

class DataStore where T : notnull { public T Data { get; set; } = default!; } // 错误,int? 为可空值类型 var store = new DataStore(); // 错误,Person? 为可空引用类型 var store = new DataStore(); // 正确 var store = new DataStore(); // 正确 var store = new DataStore();

枚举约束

从 C# 7.3 开始,C# 允许使用 System.Enum 作为基类约束,用于限制类型参数为枚举类型。

public static IEnumerable GetEnumChoices() where T : System.Enum { var values = Enum.GetValues(typeof(T)); var list = new List(); foreach (int value in values) list.Add((Enum.GetName(typeof(T), value)!, value)); return list; }

以上代码定义了一个从枚举获取值-名称对通用方法,Enum 约束让代码可以安全调用 Enum.GetValues 方法,无需额外的代码来判断类型是不是枚举。

委托约束

委托约束和枚举约束一样,也是一种特殊类型的基类约束,用于限定类型参数必须为委托。

public static TDelegate? TypeSafeCombine(this TDelegate source, TDelegate target) where TDelegate : System.Delegate => Delegate.Combine(source, target) as TDelegate;

通过使用 System.Delegate 约束,上述代码可以安全地调用 Delegate.Combine 来合并两个委托。否则就需要额外的代码来判断类型是不是委托。

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年7月1日
下一篇 2022年7月1日

相关推荐

  • 5个睡前坏习惯,你看看你有吗?

    1、睡前口渴,喝一杯水再睡? 睡前大量喝水,肾脏会承受不住,久而久之导致肾功能下降。早上起来一杯水对身体好,睡前两到三小时内不要喝水就可以了,如果口很渴了可以喝点水,晚上喝水,早上…

    2022年8月18日
  • Python基础必掌握的集合Set使用

    数学中对集合的严格定义可能是抽象的且难以掌握。但实际上可以将集合简单地认为是定义明确的不同对象的集合,通常称为元素或成员。 Python 提供了一个内置的集合类型来将对象分组到一个…

    2022年6月14日
  • 传统U盘的克星,移速奇V系列固态U盘速度是普通U盘的30倍,实测

    如果你近期准备入手一款固态U盘,那么这篇文章绝对能给你提供不少帮助。 作为一个工业领域的工程师,经常需要拷贝各类大型3DMAX文档,五年之前,我入手过一款传统的U盘,说实话,仅10…

    2022年6月12日
  • 如何利用 SpringBoot 在 ES 中实现类似链表的查询?

    一、摘要 在上篇文章中,我们详细地介绍了如何在 ES 中精准地实现嵌套json对象查询? 那么问题来了,我们如何在后端通过技术方式快速地实现 es 中内嵌对象的数据查询呢? 为了方…

    2022年7月13日
  • 初识恶魔法术激活顺序

    初识恶魔法术激活顺序是粉绿蓝,游戏中初识恶魔法术这个任务需要激活三个正确的符文,一旦选错就会导致人物死亡。该任务的激活顺序是粉绿蓝,按名称就是塔姆、塔拉尔、德尔格拉,按位置就是左侧…

    2022年7月1日
  • 这是我京东干的事,简直无语了

    虽然我是京东员工,看到这样的宣全广告我也非常气愤。你怎么能这样错误的引导大众价值观呢?不是我狭隘,各位有多少见过国外品牌这样宣全过亚洲人。真想骂人!

    2022年6月19日
  • 生物医疗实验室样本管理提高系统的执行效率

    样本库信息化管理的核心要素是利用信息化管理手段,将样本资源转化为生物学信息的过程。样本库的核心建设是信息化管理样本库的工作流程,让能够正确掌握和使用样本库信息化管理系统软件的专业人…

    2022年7月29日
  • 3.18 testparm命令 3.19 Samba 客户端工具Sambclient

    3.18 testparm命令 1.此命令行实用程序去检验Samba配置文件有无错误 如果所有配置是好的,testparm命令将返回 loaded services file ok…

    2022年7月4日
  • 抖音 Android 包体积优化探索:基于 ReDex 的 DEX 优化落地实践

    本文作者:冯瑞;廖斌斌;刘丰恺 前言 应用安装包的体积会显著影响应用的下载速度和安装速度,按照 Google 的经验数据,包体积每增加 1M 会造成 0.17%的新增折损。抖音的一…

    2022年7月3日
  • 禁用/开启 Windows系统3D加速

    前言 有的老游戏(主要是2D游戏)在新系统中运行,可能出现许多问题,如黑屏、报错、闪退、速度异常等! 这时候只需要禁用3D加速,大多即可正常运行。 当然,也可以通过这个方法,来限制…

    2022年6月22日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息