Magic behind ValueType.Equals

原文:http://blogs.msdn.com/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx

在"Effective C#"一书中,Bill Wagner写到:“在你创建值类型的时候,一定要重写ValueType.Equals()”。他主要考虑的是性能问题,在ValueType.Equals函数的默认实现里,需要使用反射枚举它所有的成员变量,开销是比较大的。

实际上,公共语言运行时针对“简单”值类型作了特殊的优化。让我们来瞧一瞧。

这是rotor中ValueType.Equals函数的实现("clr/src/bcl/system/valuetype.cs"):

bool Equals(object obj)
{
    //Compare type

    //if there are no GC references in this object we can avoid reflection
    //and do a fast memcmp
    if (CanCompareBits(this))
    {
        return FastEqualsCheck(this, obj);
    }

    //Compare using reflection
}

这里最重要的两个函数"CanCompareBits"和"FastEqualsCheck"。它们都被标记了"[MethodImpl(MethodImplOptions.InternalCall)]"属性,说明它们的实现是在公共语言运行时的内部的。

通过浏览rotor的源代码,你可以在"clr/src/vm/comutilnative.cpp"中找到这两个函数的实现。

CanCompareBits函数的注释写到:“如果值类型不包含指针或者没有填充,将返回true”。而FastEqualsCheck函数使用"memcmp"进行快速的二进制比较。

你会说,这个优化实现很不错啊,我的值类型很简单,不用自己重写Equals函数了。但是请等一下,你有没有发现CanCompareBits的问题?

问题是注释中提到的条件并不能保证二进制的比较能够得到正确的结果。

设想一下,你有一个值类型A,它只有一个float类型的成员f。你定义了两个A的对象a和b,a.f=+0.0,b.f=-0.0。从逻辑上来讲,它们应该是相等的,但是它们的二进制表示却是不同的。因此没有优化的代码将返回true,而优化之后的版本将返回false。
类似的,如果你的值类型中包含了其它重写了Equals函数的值类型,那么上述的优化都可能导致错误的结果。

这是公共语言运行时的一个bug,但是它也告诉我们,你最好为你的值类型重写Equals函数 :-)

Java企业场景下的实战入门课(Spring Boot+Redis)

04-20
<p> 企业场景下的Java实战课程!  </p> <p> 【超实用课程内容】 本课程主要是从最基础的技术要点一步一个脚印的介绍Spring Boot2.0相关的核心技术栈和缓存中间件Redis常见且典型的数据结构、相关的核心技术栈及典型的应用场景的实战。并附带业务场景实战用户注册和点赞系统中点赞功能模块的设计与实现为各位小伙伴提供企业级项目开发中常见且典型的Java核心技术,可以说是拒绝纸上谈兵、注重实战并学以致用!  </p> <p> <br> </p> <p> 套餐中一共包含2门实战入门课程(共82讲)  </p> <p> 课程1:《Java实战之Spring Boot入门到精通》  </p> <p> 课程2:《Java实战之Redis入门到精通》  </p> <p> <br> </p> <p> 【基础要求】  </p> <p> 1、基本要求:具备一定的JavaSE以及Java Web项目的开发基础、了解spring boot更佳  </p> <p> 2、工具要求:会使用Intellij IDEA、Navicat以及Postman  </p> <p> <br> </p> <p> 【你能收获到什么?】  </p> <p> 1、帮助学员了解并掌握springboot和缓存中间件Redis的方方面面、包括其典型及常用的数据结构及其在实际项目开发中典型的应用场景!  </p> <p> 2、掌握如何基于Spring Boot搭建企业级项目,整合加入中间件Redis相关的依赖配置,并以此为扩展,为后续学习其他中间件做铺垫;可以提升学员Java中间件的实战能力。  </p> <p> 3、帮助学员了解并掌握缓存中间件Redis在实际应用中有哪些常见、典型的应用场景,如对象信息存储、列表存储、队列特性分发消息、试题库随机获取、排行榜等等,这对于学员在平时项目开发、跳槽面试等情况下将有很大的帮助  </p> <p> 4、本课程介绍的基于Redis相关数据结构的特性独立设计并实战项目中典型功能模块,如会员到期自动提醒、点赞功能模块等内容,将有助于学员将所学的技术栈真正应用到实际中、提升自身的数据库设计能力、业务理解能力、代码实战能力以及性能优化方面的能力  </p> <p> <br> </p> <p> 【课程如何观看?】  </p> <p> 1、登录CSDN学院 APP 在我的课程中进行学习;  </p> <p> 2、移动端:CSDN 学院APP(注意不是CSDN APP哦) 本课程为录播课,课程2年有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 下载方式:电脑登录课程观看页面,点击右下方课程资料、代码、课件等打包下载 </p> <p> <img src="https://img-bss.csdn.net/202004200821078434.png" alt=""> </p>
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值