在C#中使用条件运算符键入结果

我试图使用条件运算符,但我对它认为结果应该是的类型挂了。

下面是一个我设法表明我遇到的问题的例子:

class Program { public static void OutputDateTime(DateTime? datetime) { Console.WriteLine(datetime); } public static bool IsDateTimeHappy(DateTime datetime) { if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0) return true; return false; } static void Main(string[] args) { DateTime myDateTime = DateTime.Now; OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime); Console.ReadLine(); ^ } | } | // This line has the compile issue ---------------+ 

在上面指出的行上,我得到以下编译错误:

无法确定条件表达式的类型,因为”和’System.DateTime’之间没有隐式转换

我很困惑因为参数是可以为空的类型(DateTime?)。 为什么需要转换呢? 如果它为null,则使用它,如果是日期时间,则使用它。

我的印象是:

 condition ? first_expression : second_expression; 

与以下相同:

 if (condition) first_expression; else second_expression; 

显然情况并非如此。 这背后的原因是什么?

(注意:我知道,如果我将“myDateTime”设为可以为空的DateTime,那么它会起作用。但为什么需要呢?

正如我之前所说,这是一个人为的例子。 在我的实际示例中,“myDateTime”是一个无法为空的数据映射值。)

编译器不会根据结果的用法推断条件运算符的结果类型,而是根据其参数的类型。 编译器在看到此表达式时失败,因为它无法推断结果的类型:

 IsDateTimeHappy(myDateTime) ? null : myDateTime; 

由于nullDateTime不兼容,您需要告诉编译器类型应该是什么。 演职员应该做的伎俩:

 DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime; OutputDateTime(x); 

现在编译器没有问题。 如果您愿意,也可以在一行上写上面的内容(但我可能不会这样做):

 OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime); 

Eric Lippert有一个很好的答案 ,在这里也很重要,并详细介绍了编译器如何确定类型。

原因是三元运算符期望两个操作数都是相同的类型。 整个运算符在分配给结果之前得到解决(在这种情况下传递给函数),因此编译器无法知道结果类型是什么。

 IsDateTimeHappy(myDateTime) ? null : myDateTime 

在上面的例子中, nullDateTime之间没有转换路径。 一旦你将其中一个投射到DateTime? ,编译器可以转换另一个:

 IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime //OR IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime 

上面的第一行代码可以工作,因为编译器可以将DateTime转换为DateTime? 通过隐式转换运算符:

 //In Nullable public static implicit operator T?(T value); 

第二行有效,因为null可以分配给DateTime? 因为后者是参考类型。

return语句不允许隐式转换。 如果你有

 if (condition) return first_expression; else return second_expression; 

然后你要比较苹果和苹果。 你没有问题 – 正如你所说的那样。

在您的情况下,您在堆栈上为DateTime分配了这么多空间 – 这是一个不可为空的值类型。 所以你要做一个对编译器没有任何意义的声明。 如果你说,我要给你一个AB ,那么AB需要是同一个东西。 在你的情况下, B永远不会是A

我想在这里也回答了这个问题: Nullable类型和三元运算符:为什么是`? 10:null`禁止?

希望这就是你所需要的。 =]

编译器说的是:

如果IsDateTimeHappy(myDateTime)false ,那么我需要返回DateTime等于myDateTime 。 如果是true ,那么我需要返回一个等于null ,但是你没有告诉我它应该是什么类型!

这就是Mark的答案就是解决方案的原因。 在提供告诉编译器的转换,如果条件为true ,将返回什么类型的值,它可以检查truefalse返回值是否可以转换为(或属于)相同类型。

干杯马克! 😉

而不是null使用default(DateTime?)然后三元的两边将具有兼容的类型。