规范约束条件

规范约束条件我们在开发时往往会对泛型指定约束条件,只有类型参数符合条件的才允许用在这个泛型上面。但是有时我们会定义过多或过少的约束条件,过多的约束条件会导致其他开发人员在使用你所编写的方法或类时做很多的工作以满足这些约束,过少的约束又会导致程序在运行的时候必须做很多的检查,并执行更多的强制类型转化操作,有时我们还需要使用反射生成运行期错误,来防止用户误用这个类。要解决这些问题,我们就必须把确实需要的约束写出来…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

我们在开发时往往会对泛型指定约束条件,只有类型参数符合条件的才允许用在这个泛型上面。但是有时我们会定义过多或过少的约束条件,过多的约束条件会导致其他开发人员在使用你所编写的方法或类时做很多的工作以满足这些约束,过少的约束又会导致程序在运行的时候必须做很多的检查,并执行更多的强制类型转化操作,有时我们还需要使用反射生成运行期错误,来防止用户误用这个类。要解决这些问题,我们就必须把确实需要的约束写出来,这句话说起来简单,其实做起来不太容易。下面我就来讲解一下如何正确的编写一个规范的约束。

零、简述

何为约束?所谓约束就是使得编译器能够知道 类型参数 除了具备 System.Object 所定义的公共接口外还需要满足的条件。在创建泛型类型时编译器必须为这个泛型类型定义有效的 IL 码,即使它不知道其中的类型参数会在什么时候替换成什么类型,也会设法创建出有效的程序集。如果我们不给它指明类型参数,那么它就会默认设置类型参数是 System.Object 类型。我们通过约束来表达对泛型类型的类型参数的约束要求会营销编译器和使用这个类的开发人员。编译器看到我们指定的约束后就会明白除了除了具备 System.Object 所定义的公共接口外还需要满足什么条件。对于编译器来说它获得了两个帮助:

  1. 可以令编译器在创建这个泛型类型的时候获得更多的信息;
  2. 编译器能够保证使用这个泛型的开发人员所提供的参数类型一定满足我们所指定的条件。

一、如何规范约束条件

讲解之前我们先来看一个例子,这个例子判断了输入的两个值是否相等。

public bool DemoEqual<T>(T t1, T t2)
{ 
   
    if(t1==null)
    { 
   
        return t2==null;
    }
    if(t1 is IComparable<T>)
    { 
   
        IComparable<T> val1 = t1 as IComparable<T>;
        if(t2 as IComparable<T>)
        { 
   
            return val1.CompareTo(t2)==0;
        }
        else
        { 
   
            throw new ArgumentException($"{ 
     nameof(t2)} 没有实现 IComparable<T>");
        }
    }
    else
    { 
   
        throw new ArgumentException($"{ 
     nameof(t1)} 没有实现 IComparable<T>")
    }
}

这段代码中执行了大量的强类型转换,在转换之前还判断时传入的参数是否实现了 IComparable 接口。这段代码如果使用了泛型约束就会很简单:

public bool DemoEqual<T>(T t1, T t2) 
    where T : IComparable<T>
        => t1.CompareTo(t2)==0;

这段代码大大简化了前面的那段代码,并且把程序运行期可能出现的错误提前到了编译期,编译器提前阻止了不符合要求的用法。到这里你是不是以为上述代码就是很好的解决方案呢?其实严格来说上述代码矫枉过正了,为什么这么说呢?因为 IComparable 接口很常见,大部分开发人员在设计类型的时候都会事先这个接口,因此我们将上述代码修改一些,我们不使用 CompareTo 来对比两个值是否相等,我们这次使用 Equals 来对比:

public bool DemoEqual<T>(T t1, T t2) 
    => t1.Equals(t2);

上述代码有一点需要注意,如果 DemoEqual 是定义在泛型类里,并且泛型类也规定了 IComparable 约束,那么他调用的 Equals 是 IComparable.Equals ,反之调用的就是 System.Object.Equals 。这两个 Equals 在性能上没什么大的差别,前者的执行效率只比后者高了那么一丢丢,因为它只是不用在运行时检查程序有没有重写 System.Object.Equals ,以及泛型参数类型为值类型时它也不用执行装箱和拆箱操作。但是对于把性能看的特别重的开发人员来说,前者是最优的方案。

Tip:如果有较好的方法,我还是建议大家使用较好的方法,比如前面我们所说的 IComparable.Equals 。

我们在编写泛型类的时候,最好在内部编写相互重载的多个方法,这样就可以针对不同的情况调用不同的方法,并且其他开发人员调用起来也不会有过于严谨的约束。有时候我们定义的约束过于严谨,会导致泛型类的适用范围很狭窄,遇到这种情况时我们就应该考虑我们自己在泛型类种编写代码来判断传入的类型是否继承自某个类或者实现了某个接口。在泛型约束中有三种约束我们必须谨慎使用,它们就是 new 、 struct 以及 class 约束,因为它们会限定对象的构建方式,除非你要求对象的默认值必须是 0 、null 或者必须能以 new() 的形式创建,那么我们才可以使用这三种约束。

二、总结

约束是为了向调用方提出要求,但是如果约束太多调用方就需要做更多的工作来满足这些约束,因此在创建约束时应该权衡利弊,将多余的约束去掉只保留需要的约束。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/182362.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 删除windows默认共享[通俗易懂]

    删除windows默认共享  Windows2000的缺省安装很容易被攻击者取得账号列表,即使安装了最新的Servicepack也是如此。在Windows2000中有一个缺省共享IPC$,并且还有诸如admin$C$D$等等,而IPC$允许匿名用户(即未经登录的用户)访问,利用这个缺省共享可以取得用户列表。要想防范这些,可将在“管理工具→本地安全策略→安全设置→本地策略→

  • sas ods html的作用是什么意思,SAS ODS「建议收藏」

    sas ods html的作用是什么意思,SAS ODS「建议收藏」SAS程序的输出可以转换为更加用户友好的形式,如.html或PDF。这是通过使用SAS中提供的ODS语句来完成的。ODS代表输出传递系统。它主要用于格式化SAS程序的输出数据到好的报告,这是很好看的和理解。这也有助于与其他平台和软件共享输出。它还可以将多个PROC语句的结果合并在一个文件中。语法在SAS中使用ODS语句的基本语法是:ODSoutputtypePATHpathname…

  • linux中wq(linux a)

    LinuxESC:wq和:wq!的区别LinuxESC:wq和:wq!的区别发布者:IT人在线|发表时间:2018-12-417:20:43LinuxESC:wqesc(键退出)->:(符号输入)->wq(保存退出)wq(存盘并退出write%quite)即使文件没有被修改也强制写入,并更新文件的修改时间。:wq和:wq!的区别::wq(保存编辑操作退出)强…

  • android HorizontalScrollView讲解[通俗易懂]

    android HorizontalScrollView讲解[通俗易懂]前言  本章内容是android.widget.HorizontalScrollView,译为”横向滚动条”,版本为Android2.3r1,翻译来自”Tina”,感谢”Tina”为大家带来精彩的翻译稿!期待你加入AndroidAPI中文的翻译,联系我over140@gmail.com。 声明  欢迎转载,但请保留文章原始出处:)    JavaEye社区:htt

  • linux系统怎么数据恢复,linux系统数据恢复

    linux系统怎么数据恢复,linux系统数据恢复程序员的误操作造成数据丢失,忙着一个星期的项目,就这样付之东流了。老板的痛斥、经理的训斥接踵而来。接下来就是没休息、加班,甚至忙到凌晨都不能离开那该死的电脑,都有种想屎的感觉呢?为那些不喜欢备份数据的朋友带来了福音,我们来谈谈数据恢复,这里我们来手把手地教会你如何利用简单的工具来恢复被你删除的数据。工具:hexedit、fdisk下文内容操作均在root环境下完成。hexedit:在linux上…

  • linux 安装 RabbitMQ「建议收藏」

    下载ErlangRabbitMQ是由erlang语言编写的,所以在安装rabbitMQ之前需要安装Erlang.erlang下载地址:Downloads-Erlang/OTP这里下载23.3版本。下载rabbitMQ在rabbitMQ官网可以看到mq版本对应的erlang的版本。点击上述地址中的rabbitMQ安装指南,可以在里面下载安装包…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号