简体   繁体   English

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

[英]Type result with conditional operator in C#

I am trying to use the conditional operator, but I am getting hung up on the type it thinks the result should be. 我正在尝试使用条件运算符,但我正在挂起它认为结果应该是的类型。

Below is an example that I have contrived to show the issue I am having: 下面是一个我设法表明我遇到的问题的例子:

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  ---------------+

On the line indicated above, I get the following compile error: 在上面指出的行上,我得到以下编译错误:

Type of conditional expression cannot be determined because there is no implicit conversion between '< null >' and 'System.DateTime' 无法确定条件表达式的类型,因为'<null>'和'System.DateTime'之间没有隐式转换

I am confused because the parameter is a nullable type (DateTime?). 我很困惑因为参数是可以为空的类型(DateTime?)。 Why does it need to convert at all? 为什么需要转换呢? If it is null then use that, if it is a date time then use that. 如果它为null,则使用它,如果是日期时间则使用它。

I was under the impression that: 我的印象是:

condition ? first_expression : second_expression;

was the same as: 与以下相同:

if (condition)
   first_expression;
else
   second_expression;

Clearly this is not the case. 显然情况并非如此。 What is the reasoning behind this? 这背后的原因是什么?

(NOTE: I know that if I make "myDateTime" a nullable DateTime then it will work. But why does it need it? (注意:我知道如果我将“myDateTime”设为可以为空的DateTime,那么它将会起作用。但为什么需要呢?

As I stated earlier this is a contrived example. 正如我之前所说,这是一个人为的例子。 In my real example "myDateTime" is a data mapped value that cannot be made nullable.) 在我的实例中,“myDateTime”是一个数据映射值,不能为空。)

The compiler does not infer the type of the result of the conditional operator from the usage of the result, but from the types of its arguments. 编译器不会根据结果的用法推断条件运算符的结果类型,而是根据其参数的类型。 The compiler fails when it sees this expression because it cannot deduce the type of the result: 编译器在看到此表达式时失败,因为它无法推断出结果的类型:

IsDateTimeHappy(myDateTime) ? null : myDateTime;

Since null and DateTime are not compatible, you need to tell the compiler what the type should be. 由于nullDateTime不兼容,您需要告诉编译器类型应该是什么。 A cast should do the trick: 演职员应该做的伎俩:

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

Now the compiler will have no problems. 现在编译器没有问题。 You can also write the above on one line if you prefer (but I would probably not do this): 如果您愿意,也可以在一行上写上面的内容(但我可能不会这样做):

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

Eric Lippert has a good answer that is also relevant here and goes into more details about how the compiler determines types. Eric Lippert有一个很好的答案 ,这里也很重要,并详细介绍了编译器如何确定类型。

The reason is the ternary operator expects both the operands to be of the same type. 原因是三元运算符期望两个操作数都是相同的类型。 The whole operator get worked out BEFORE it is assigned to a result (in this case passed into a function), so the compiler can't know what the result type is. 整个运算符在分配给结果之前得到解决(在这种情况下传递给函数),因此编译器无法知道结果类型是什么。

IsDateTimeHappy(myDateTime) ? null : myDateTime

In the above case there is no conversion path between null and DateTime . 在上面的例子中, nullDateTime之间没有转换路径。 As soon as you cast one of them to DateTime? 一旦你将其中一个投射到DateTime? , the compiler can convert the other one: ,编译器可以转换另一个:

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

The fist line of code above works because the compiler can convert DateTime to DateTime? 上面的第一行代码是DateTime ,因为编译器可以将DateTime转换为DateTime? via an implicit conversion operator: 通过隐式转换运算符:

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

The second line works because null can be assigned to DateTime? 第二行有效,因为null可以分配给DateTime? since the latter is a reference type. 因为后者是参考类型。

The implicit conversion is not allowed by the return statement. return语句不允许隐式转换。 If you had 如果你有

if (condition)
    return first_expression;
else
    return second_expression;

Then you'd be comparing apples to apples. 然后你要比较苹果和苹果。 And you'd have no problems - as you stated. 而且你没有问题 - 正如你所说的那样。

In your case, you're allocated so much space on the stack for a DateTime - which is a non-nullable value type. 在您的情况下,您在堆栈上为DateTime分配了这么多空间 - 这是一种不可为空的值类型。 So you're making a statement that doesn't make any sense to the compiler. 所以你要做一个对编译器没有任何意义的声明。 If you say, I'm going to pass you an A or a B , then the A and the B need to be the same thing. 如果你说,我要给你一个AB ,那么AB需要是同一个东西。 In your case, the B can never be an A . 在你的情况下, B永远不会是A

I think this is also answered here: Nullable types and the ternary operator: why is `? 我想在这里也回答: 可空类型和三元运算符:为什么是`? 10 : null` forbidden? 10:null`禁止?

Hope that's what you needed. 希望这就是你所需要的。 =] =]

What the compiler is saying is: 编译器说的是:

If IsDateTimeHappy(myDateTime) is false , then I need to return a value of type DateTime equal to myDateTime . 如果IsDateTimeHappy(myDateTime)false ,那么我需要返回DateTime等于myDateTime If it is true , then I need to return a value equal to null , but you haven't told me what type it should be! 如果是true ,那么我需要返回等于值null ,但是你还没有告诉我应该是什么样的!

That's why Mark's answer is the solution. 这就是Mark的答案就是解决方案的原因。 After you provide a cast telling the compiler what type of value will be returned if the condition is true , it can check whether the true and false return values can be converted to (or are of) the same type. 在提供告诉编译器的转换为条件为true将返回什么类型的值之后,它可以检查truefalse返回值是否可以转换为(或属于)相同类型。

Cheers Mark! 干杯马克! ;-) ;-)

而不是null使用default(DateTime?)然后三元的双方都必须兼容的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM