最少的C#代码 [英] Minimal code for equality in C#

查看:140
本文介绍了最少的C#代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此文章中,埃里克·利珀特在第9点中暗示C#具有太多的平等。他指出,可以重载9或10种不同的方法或运算符以提供对象相等性。



我的第一个问题是-如果Object.Equals(object)方法被覆盖,编译器是否可以在没有明确执行此操作的代码的情况下调用==,!=,< =等其他相等运算符?



在C ++中,有此行为的先例。复制构造函数可以在需要生成临时变量的某些位置由编译器调用。我至少95%确信这在C#中不会发生,但这实际上取决于编译器的构造方式以及边缘情况。



第二个问题是-如果编译器永远不会间接调用任何相等运算符,那么对于小型,中型甚至大型项目,只要指定仅使用Object.Equals(object)方法和IEquatable进行相等性就可以了测试,如果需要确定对象的等级时将使用IComparable进行类型排序或其他时间使用?换句话说-如果项目中的每个人都同意不会使用它们,因此是不必要的,可以避免定义其他相等运算符吗?



假定该代码仅在项目内使用,并且不会导出供第三方使用。

解决方案


如果 Object.Equals(object)方法被覆盖,是否有可能编译器调用其他任何相等运算符,例如 == != < ; = 等没有明确执行此操作的代码?


C#编译器不知道等于 == 在语义上是相同的。如果您调用 Equals ,则将调用该方法。


然后会是小型,中型甚至大型项目都可以指定仅 Object.Equals(object)方法和 IEquatable 是否用于相等性测试,而 IComparable 是否用于将类型用于排序或在需要确定对象等级时其他时间使用?换句话说-如果项目中的每个人都同意不会使用它们,因此是不必要的,可以避免定义其他相等运算符吗?


这里遇到的危险是您得到 == 运算符为您定义的默认情况下引用平等。您很容易会遇到这样的情况,其中重载的 Equals 方法会确定相等性,而 == 会引用相等性,并且那么您会意外地在价值相等的非参照相等的事物上使用参照相等。



几年前,我研究了一种静态分析算法,以统计方式检测这种情况,并且我们发现在我们研究的所有代码库中,每百万行代码中大约有两个实例的缺陷率。当只考虑覆盖了等于的代码库时,缺陷率显然要高得多!



此外,请考虑成本与风险。如果您已经具有 IComparable 的实现,那么编写所有运算符将是一件简单的事情,不会有错误,也永远不会更改。这是您要编写的最便宜的代码。如果在编写和测试十二种微小方法的固定成本与在使用引用相等而不是值相等的情况下发现和修复一个很难见的bug的无限成本之间做出选择,我知道我会选择哪一个。 / p>

In this article, Eric Lippert suggests in point #9 that C# has "too much equality". He points out that there are 9 or 10 different methods or operators that can be overloaded to provide object equality.

My first question is - if the Object.Equals(object) method is overridden, is it possible for the compiler to call any of the other equality operators like ==, !=, <=, etc. without code that expressly performs this operation?

In C++, there is precedent for this behavior. The copy constructor can be called by the compiler in certain places where a temporary variable needs to be generated. I'm at least 95% certain that this can't happen in C#, but it really depends on how the compiler is constructed and maybe edge cases as well.

The second question is - if the compiler will never call any of the equality operators indirectly, then would it be ok for a small, medium, or even large project to specify that only the Object.Equals(object) method and IEquatable be used for equality testing, and IComparable used if the type will be used for sorting or other times when determining the rank of the objects is needed? In other words - is it ok to avoid defining the other equality operators if everyone on the project agrees they won't be used and are therefore unnecessary?

Assume that the code is only to be used within the project and won't be exported for use by third parties.

解决方案

if the Object.Equals(object) method is overridden, is it possible for the compiler to call any of the other equality operators like ==, !=, <=, etc. without code that expressly performs this operation?

The C# compiler has no idea that Equals and == are semantically the same. If you call Equals then that method will be called.

then would it be ok for a small, medium, or even large project to specify that only the Object.Equals(object) method and IEquatable be used for equality testing, and IComparable used if the type will be used for sorting or other times when determining the rank of the objects is needed? In other words - is it ok to avoid defining the other equality operators if everyone on the project agrees they won't be used and are therefore unnecessary?

The danger you run into here is that you get an == operator defined for you that does reference equality by default. You could easily end up in a situation where an overloaded Equals method does value equality and == does reference equality, and then you accidentally use reference equality on not-reference-equal things that are value-equal. This is an error-prone practice that is hard to spot by human code review.

A couple years ago I worked on a static analysis algorithm to statistically detect this situation, and we found a defect rate of about two instances per million lines of code across all codebases we studied. When considering just codebases which had somewhere overridden Equals, the defect rate was obviously considerably higher!

Moreover, consider the costs vs the risks. If you already have implementations of IComparable then writing all the operators is trivial one-liners that will not have bugs and will never be changed. It's the cheapest code you're ever going to write. If given the choice between the fixed cost of writing and testing a dozen tiny methods vs the unbounded cost of finding and fixing a hard-to-see bug where reference equality is used instead of value equality, I know which one I would pick.

这篇关于最少的C#代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆