Argument order for '==' with Nullable<T>

别说谁变了你拦得住时间么 提交于 2019-12-03 01:37:16

So I was curious about the answer and took a look at the c# 6 specification (no clue where the c# 7 spec is hosted). Full disclaimer: I do not guarantee that my answer is correct, because I did not write the c# spec/compiler and my understanding of the internals is limited.

Yet I think that the answer lies in the resultion of the overloadable == operator. The best applicable overload for == is determined by using the rules for better function members.

From the spec:

Given an argument list A with a set of argument expressions {E1, E2, ..., En} and two applicable function members Mp and Mq with parameter types {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn}, Mp is defined to be a better function member than Mq if

for each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

What caught my eye is the argument list {E1, E2, .., En}. If you compare a Nullable<bool> to a bool the argument list should be something like {Nullable<bool> a, bool b}and for that argument list the Nullable<bool>.Equals(object o) method seems to be the best function, because it only takes one implicit conversion from bool to object.

However if you revert the order of the argument list to {bool a, Nullable<bool> b} the Nullable<bool>.Equals(object o) method no longer is the best function, because now you would have to convert from Nullable<bool> to bool in the first argument and then from bool to object in the second argument. That's why for case A a different overload is selected which seems to result in cleaner IL code.

Again this is an explanation that satisfies my own curiosity and seems to be in line with the c# spec. But I have yet to figure out how to debug the compiler to see what's actually going on.

ivan_pozdeev

Looks like the 1st operand is converted to the 2nd's type for the purpose of comparison.

The excess operations in case B involve constructing a Nullable<bool>(true). While in case A, to compare something to a true/false, there's a single IL instruction (brfalse.s) that does it.

I couldn't find the specific reference in the C# 5.0 spec. 7.10 Relational and type-testing operators refers to 7.3.4 Binary operator overload resolution that in turn refers to 7.5.3 Overload resolution, but the latter one is very vague.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!