Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shouldn't if(1 == null) cause an error? [duplicate]

Tags:

c#

Int32 struct doesn't define operator overload method for == operator, so why doesn't the code cause compile time error:

if(1 == null) ... ;
like image 979
user702769 Avatar asked May 06 '11 18:05

user702769


2 Answers

Let's take a step back here. The question is confusing and the answers so far are not very clear as to what is going on here.

Shouldn't if(1 == null) cause an error?

No. That is legal, though dumb.

How does the compiler deal with operators like "=="? It does so by applying the overload resolution algorithm.

The first thing we must determine is whether this is a "user defined" equality operator or a "built in" equality operator. The left side is a built-in type. The right side has no type at all. Neither of those are user-defined types. Therefore no user-defined operator will be considered. Only built-in operators will be considered.

Once we know that, the question is "which built-in operators will be considered?" The built in operators are described in section 7.10 of the spec. They are equality operators on int, uint, long, ulong, decimal, float, double, any enum type, bool, char, object, string and any delegate type.

All of the equality operators on value types also have a "lifted" form that takes nullable value types.

We must now determine which of those operators are applicable. To be applicable, there must be an implicit conversion from both sides to the operator's type.

There is no implicit conversion from int to any enum type, bool, string or any delegate type, so those all vanish from consideration.

(There is not an implicit conversion from int to uint, ulong, etc, but since this is a literal one, there is an implicit conversion from 1 to uint, ulong, etc.)

There is no implicit conversion from null to any non-nullable value type, so those all disappear too.

What does that leave? That leaves the operators on object, int?, long?, uint?, ulong?, double?, float?, decimal? and char? the remaining nullable types.

We must now determine which one of those remaining applicable candidates is the unique "best" operator. An operator is better than another operator if its operand type is more specific. "object" is the least specific type, so it is eliminated. Clearly every nullable int can be converted to nullable long, but not every nullable long can be converted to nullable int, so nullable long is less specific than nullable int. So it is eliminated. We continue to eliminate operators in this manner. (In the case of the unsigned types we apply a special rule that says that if int? and uint? are both options then int? wins.)

I will spare you the details; ultimately that process leaves nullable int as the unique best operand type.

Therefore your program is interpreted as if((int?)1 == (int?)null), which clearly is legal, and will always be false.

Int32 struct doesn't define operator overload method for == operator

You are correct. What does that have to do with anything? The compiler is perfectly able to do the analysis without it. I don't understand the relationship you believe this fact has to your question. The fact is about a method that could be defined on a type, the question is about how overload resolution chooses a lifted built-in operator. Those two things are not related because "int" is not a user-defined type.

like image 74
Eric Lippert Avatar answered Oct 09 '22 05:10

Eric Lippert


It is a value type rather than a reference type. So it will not need operators.

http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

like image 35
iain Avatar answered Oct 09 '22 05:10

iain