简体   繁体   English

条件运算符?:具有Nullable类型的Casting

[英]Conditional Operator ?: with Nullable type Casting

From the MSDN documentation, the following two snippets are equal: 从MSDN文档中,以下两个片段是相同的:

bool value;
int x = (value) ? 0 : 1;

And

bool value;
int x;
if (value)
    x = 0;
else
    x = 1;

Great, wonderful. 太棒了,很棒。 I use it all the time. 我用它所有的时间。 Terse and effective. Terse和有效。

If we try this with a nullable type, like so: 如果我们尝试使用可空类型,如下所示:

int? x = (value.HasValue) ? value.Value : null;

We get a compile-time error: 我们得到一个编译时错误:

The type of conditional expression cannot be determined
because there is no implicit conversion between '{NullableType}' and null.

This compiles fine: 编译好:

int? value;
int? x;

if (value.HasValue)
    x = value.Value;
else
    x = null;

So, I understand that the compiler requires an explicit cast in the way of (int?)null to compile the first statement. 所以,我理解编译器需要以(int?)null的方式显式转换以编译第一个语句。 What I don't understand is why it is required in that statement, but not the If Else block. 我不明白的是为什么在该声明中需要它,而不是If Else块。

null can represent any object-based datatype. null可以表示任何基于对象的数据类型。 You need to cast null as a datatype so it know what you are talking about. 您需要将null为数据类型,以便它知道您在说什么。

int? x = (value.HasValue) ? value.Value : (int?)null;

I know, it sounds a bit strange. 我知道,这听起来有点奇怪。


To answer the questions in the comments: 要回答评论中的问题:

Why is it not implicit though? 为什么不隐含呢?
Yeah, I get that. 是的,我明白了。 But why do I not have to cast it in a If Else block? 但为什么我不必将它转换为If Else块?

Let's walk through the code. 让我们来看看代码。

Your else statement looks like this: 你的else语句如下:

else x = null;

This means you are assigning the value of null to x . 这意味着您要将nullnull x This is valid, because x is a int? 这是有效的,因为x是一个int? , which takes nulls . nulls

The difference comes when you have the ternary operator. 当你有三元运算符时,差异就出现了。 It says: "assign the value of the operator into x ". 它说:“将运算符的值分配给x ”。 The question (and the reason for your error) is, what datatype is the result of the ternary operator? 问题(以及错误的原因)是,三元运算符的结果是什么数据类型?

From your code, you can't be sure, and the compiler throws its hands up. 从您的代码中,您无法确定,并且编译器会引起轰动。

int? x = (value.HasValue) ? value.Value : null;
// int?        bool             int        ??

What datatype is null ? 什么数据类型为null You are quick to say "well it's a int? , because the other side is a int and the result is a int? ". 你很快就会说“好吧它是一个int?因为另一边是int而结果是int? ”。 The problem is, what about the following: 问题是,如下:

string a = null;
bool? b = null;
SqlConnectionStringBuilder s = null;

This is also valid, which means null can be used for any object-based datatype . 这也是有效的,这意味着null可以用于any object-based datatype This is why you have to explicitly cast null as the type you want to use, because it can be used for anything! 这就是为什么你必须显式地将null为你想要使用的类型,因为它可以用于任何事情!


Another explanation (and possible more accurate): 另一种解释(可能更准确):

You can't have an implicit cast between a nullable and a non-nullable value. 您不能在可空值和非可空值之间进行隐式转换。

int is not-nullable (it's a structure), where null is. int是不可为空的(它是一个结构),其中null是。 This is why in Habib's answer you can put the cast on either the left or right side. 这就是为什么在Habib的回答中你可以将演员放在左侧或右侧。

For Condtional operator MSDN states: 对于Condtional运营商MSDN状态:

Either the type of first_expression and second_expression must be the same , or an implicit conversion must exist from one type to the other. first_expression和second_expression的类型必须相同 ,或者从一种类型到另一种类型必须存在隐式转换

So in you case your first_expression and second_expression are: 所以在你的情况下你的first_expression和second_expression是:

int? x = (value.HasValue) ? value.Value : null;
                             ^^^^^^^^      ^^^^^
                             first exp     2nd Exp

Now if you see, your First Expression is of type int , and second expression is null and both are not same and there is no implicit conversion. 现在,如果你看到,你的First Expression是int类型,第二个表达式是null ,两者都不相同,也没有隐式转换。 So casting any of them to `int? 所以将它们中的任何一个转换为`int? solves the problem. 解决了这个问题。

So: 所以:

int? x = (value.HasValue) ? (int?) value.Value : null;

Or 要么

int? x = (value.HasValue) ? value.Value : (int?) null;

are fine. 没事。

Now why it is not required with if-else , because there multiple statements involved and it not a single statement assigning the value. 现在为什么if-else不需要它,因为涉及多个语句而且它不是分配值的单个语句。

var x = value.HasValue ? value.Value : default(int?);

也有效。

The documentation for the ?: operator states that the type of the expression b ? ?:运算符文档说明了表达式b的类型? x : y is determined by examining the types of x and y: x:y是通过检查x和y的类型来确定的:

  • If X and Y are the same type, then this is the type of the conditional expression. 如果X和Y是相同的类型,那么这是条件表达式的类型。
  • Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression. 否则,如果从X到Y存在隐式转换(第6.1节),而不是从Y到X,则Y是条件表达式的类型。
  • Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression. 否则,如果从Y到X存在隐式转换(第6.1节),而不是从X到Y,则X是条件表达式的类型。
  • Otherwise, no expression type can be determined, and a compile-time error occurs. 否则,无法确定表达式类型,并发生编译时错误。

In your example 在你的例子中

int? x = (value.HasValue) ? value.Value : null;

there is no implicit conversion between int and null so the last bullet applies. int和null之间没有隐式转换,因此最后一个项目符号适用。

The reason is that the type of conditional expression is determined by the second and third operators of the conditional operator (?:) . 原因是条件表达式的类型由条件运算符(?:)的第二个和第三个运算符确定。

Since null has no type, the compiler cannot determine the type of the overall expression so it emits a compiler error. 由于null没有类型,因此编译器无法确定整个表达式的类型,因此会发出编译器错误。

The reason it works with the simple assignment operator (=) is because the left side of the operator determines the the type. 它与简单赋值运算符(=)一起使用的原因是因为运算符的左侧确定了类型。 Since in the If statement, the type of x is already known, the compiler doesn't complain. 因为在If语句中,x的类型已经知道,所以编译器不会抱怨。

See section 7.14 (Conditional operator) and section 7.17.1 (Simple assignment) for further explanations. 有关详细说明,请参见第7.14节(条件运算符)和第7.17.1节(简单赋值)。

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

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