【问题标题】:Type result with conditional operator in C#在 C# 中使用条件运算符键入结果
【发布时间】:2023-03-26 02:53:02
【问题描述】:

我正在尝试使用条件运算符,但我对它认为结果应该是的类型感到困惑。

以下是我试图展示我遇到的问题的示例:

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?)。为什么它需要转换?如果为空,则使用它,如果是日期时间,则使用它。

我的印象是:

condition ? first_expression : second_expression;

与以下内容相同:

if (condition)
   first_expression;
else
   second_expression;

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

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

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

【问题讨论】:

标签: c# type-conversion nullable ternary-operator conditional-operator


【解决方案1】:

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

IsDateTimeHappy(myDateTime) ? null : myDateTime;

由于null和DateTime不兼容,你需要告诉编译器应该是什么类型。演员应该可以解决问题:

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

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

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

Eric Lippert 有一个good answer,这也与此处相关,并详细介绍了编译器如何确定类型。

【讨论】:

  • 将 myDateTime 声明为 DateTime? 开头的也不那么冗长的解决方案:DateTime? myDateTime = DateTime.Now;
【解决方案2】:

原因是三元运算符希望两个操作数属于同一类型。整个运算符在分配给结果(在这种情况下传递给函数)之前就已计算出来,因此编译器无法知道结果类型是什么。

IsDateTimeHappy(myDateTime) ? null : myDateTime

在上述情况下,null 和 DateTime 之间没有转换路径。只要将其中一个转换为DateTime?,编译器就可以转换另一个:

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

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      if (condition)
          return first_expression;
      else
          return second_expression;
      

      那么您将苹果与苹果进行比较。而且你不会有任何问题 - 正如你所说的那样。

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

      【讨论】:

        【解决方案5】:

        编译器的意思是:

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

        这就是为什么马克的答案是解决方案。在你提供一个转换告诉编译器如果条件是true 将返回什么类型的值之后,它可以检查true 和false 返回值是否可以转换为(或属于)相同的类型。

        干杯马克! ;-)

        【讨论】:

          猜你喜欢
          • 2011-02-06
          • 1970-01-01
          • 2022-11-23
          • 1970-01-01
          • 2012-08-21
          • 2013-07-25
          • 2011-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多