Type result with conditional operator in C#

喜欢而已 提交于 2019-11-27 05:06:24
Mark Byers

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

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. As soon as you cast one of them to 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? 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? since the latter is a reference type.

The implicit conversion is not allowed by the return statement. 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. 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. In your case, the B can never be an A.

iffy

I think this is also answered here: Nullable types and the ternary operator: why is `? 10 : null` forbidden?

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. 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!

That's why Mark's answer is the solution. 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.

Cheers Mark! ;-)

Instead of null use default(DateTime?) and then both sides of the ternary will have compatible types.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!