问题
Following expression is ok
short d = ("obj" == "obj" ) ? 1 : 2;
But when you use it like below, syntax error occurs
short d = (DateTime.Now == DateTime.Now) ? 1 : 2;
Cannot implicitly convert type 'int' to 'short'. An explicit conversion exists (are you missing a cast?)
Can anyone explain why this is so?
Is there a difference between comparing string-to-string and datetime-to-datetime in a ternary operator, why?
I would be grateful if you could help me.
回答1:
C# language specification, version 5, section 6.1.9:
An implicit constant expression conversion permits the following conversions:
- A constant-expression (§7.19) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
Your first example is a constant expression, because it can be evaluated at compile time. But see section 7.19 for more details:
Only the following constructs are permitted in constant expressions:
- Literals (including the null literal).
[...]
- The predefined +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
- The ?: conditional operator.
回答2:
I believe in the first case the compiler knows that the strings are equal at compile time and therefore optimizes the code to just:
short d = 1;
That works because 1
can be assigned to short
variable.
In the second case optimization cannot happen because compiler cannot infer equality at compile time, so it leaves:
short d = (DateTime.Now == DateTime.Now) ? (long)1 : (long)2;
This will compile:
short d = (DateTime.Now == DateTime.Now) ? (short)1 : (short)2;
IL (LinqPad) for call short d = ("obj" == "obj" ) ? 1 : 2;:
IL_0001: ldc.i4.1
IL_0002: stloc.0 // d
回答3:
"obj" == "obj" can be resolved at compile time; compiler treats it as
short d = 1;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
short d = ("obj" == "obj") ? 1 : 2;
}
}
}
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 4 (0x4)
.maxstack 1
.locals init ([0] int16 d)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ret
} // end of method Program::Main
DateTime.Now == DateTime.Now can't be resolved at compile time and throws an error.
来源:https://stackoverflow.com/questions/21781096/ternary-operator-behaviour-inconsistency