在String.Equals中使用C#ternary

时间:2021-10-20 16:15:39

This works:

这有效:

short value;
value = 10 > 4 ? 5 : 10;

This works:

这有效:

short value;
value = "test" == "test" ? 5 : 10;

This doesn't work:

这不起作用:

short value;
string str = "test";
value = "test" == str ? 5 : 10;

Neither does this:

这也不是:

short value;
string str = "test";
value = "test".Equals(str) ? 5 : 10;

The last two cases I am getting the following error:

最后两种情况我收到以下错误:

Cannot implicitly convert type 'int' to 'short'.
An explicit conversion exists (are you missing a cast?)

Why do I have to cast on the last two cases and not on the two first cases?

为什么我必须对最后两个案例进行演绎,而不是对前两个案例进行演绎?

4 个解决方案

#1


44  

short value;
value = 10 > 4 ? 5 : 10;             //1
value = "test" == "test" ? 5 : 10;   //2
string str = "test";
value = "test" == str ? 5 : 10;      //3
value = "test".Equals(str) ? 5 : 10; //4

The last two ternary expressions (3,4) cannot be resolved to a constant at compile time. Thus the compiler treats the 5 and 10 as int literals, and the type of the entire ternary expression is int. To convert from an int to a short requires an explicit cast.

最后两个三元表达式(3,4)在编译时无法解析为常量。因此编译器将5和10视为int文字,整个三元表达式的类型为int。要从int转换为short,需要显式转换。

The first two ternary expressions (1,2) can be resolved to a constant at compile time. The constant value is an int, but the compiler knows it fits in a short, and thus does not require any casting.

前两个三元表达式(1,2)可以在编译时解析为常量。常量值是一个int,但编译器知道它适合短,因此不需要任何转换。

For fun, try this:

为了好玩,试试这个:

value = "test" == "test" ? 5 : (int)short.MaxValue + 1;

#2


4  

You need a cast to make the two last examples work

你需要一个演员才能使最后两个例子有效

value = (short)("test" == str ? 5 : 10);

Why dont't you need it in the first two?

为什么你不需要在前两个?

Because the first two are compile-time constants. The compiler is able to translate 10 > 4 ? 5 : 10 to true ? 5 : 10, then to just 5

因为前两个是编译时常量。编译器能够翻译10> 4? 5:10为真吗? 5:10,然后到5

So when you write

所以当你写作

value = 10 > 4 ? 5 : 10;

It's effectively the same as

它实际上是一样的

value = 5;

which compiles because the compiler is allowed to implicitly cast constants if they are in the allowed range.

编译是因为如果允许编译器在允许的范围内,则允许隐式转换常量。

Conversely, "test" == str ? 5 : 10; is not a compile time constant, so the compile is not allowed to implcitly cast it. You need to make an explicit cast yoursef.

相反,“测试”== str? 5:10;不是编译时常量,因此不允许编译强制转换它。你需要做一个明确的演员yoursef。

#3


3  

This is defined by the C# Language Specification, of course.

当然,这是由C#语言规范定义的。

The key thing to be aware of is that there are two kinds of conversions from int to short. One is an explicit conversion which always applies but which requires you to write (short) explicitly before the int expression. The other one is an implicit constant expression conversion which only applies when (a) the int expression is a compile-time constant and (b) the value of this compile-time expression is within the range of a short, that is -32768 through 32767.

需要注意的关键是从int到short有两种转换。一种是显式转换,它始终适用但需要您在int表达式之前显式写入(short)。另一个是隐式常量表达式转换,仅当(a)int表达式是编译时常量和(b)此编译时表达式的值在short的范围内时才适用,即-32768到32767。

A literal like 5, 10 or 4 has type int in C# (that goes for any integer literal which is between -2147483648 and 2147483647 and not followed by a symbol L, U or similar). So if we look at the right-hand sides of all your assignments, they are clearly int expressions, not short.

像5,10或4这样的文字在C#中具有int类型(适用于-2147483648和2147483647之间的任何整数文字,并且后面没有符号L,U或类似符号)。因此,如果我们查看所有作业的右侧,它们显然是int表达式,而不是简短的。

In the case 10 > 4 ? 5 : 10, since 10 and 4 are compile-time constants, this is the same as true ? 5 : 10 because the > operator between ints is built-in and will result in a constant when the operands are constants. And in the same way true ? 5 : 10 gives 5 because all three operands are constants, and ?: is classified a constant itself in that case. So it really says:

在10> 4的情况下? 5:10,因为10和4是编译时常量,这是真的吗? 5:10因为int之间的>运算符是内置的,并且当操作数是常量时将导致常量。并以同样的方式真实? 5:10给出5,因为所有三个操作数都是常数,而?:在这种情况下被归类为常数。所以它真的说:

short value = 5;

where the "5" is a compile-time constant. Hence it is checked at compile-time if the int 5 is within the range (it does not matter with the 10, it could be 999999), and since that is the case, the implicit constant expression conversion applies, and it is legal.

其中“5”是编译时常量。因此,在编译时检查int 5是否在范围内(与10无关,它可能是999999),并且由于这种情况,隐式常量表达式转换适用,并且它是合法的。

Note that you can do the same with:

请注意,您可以执行以下操作:

const int huge = 10;
const int tiny = 4;
const int significant = 5;
const int unimporatnt = 10;
short value;
value = huge > tiny ? significant : unimportant;

as long as all the operands are const variables (pun?).

只要所有操作数都是const变量(双关语?)。

Now, if I managed to make the explanation clear, you will also know by now that the obstacle preventing value = "test" == str ? 5 : 10; from working is that you did not mark the str local as const. Do that, and it will be allowed.

现在,如果我设法解释清楚,你现在也知道障碍阻止值=“test”== str? 5:10;从工作是你没有将str local标记为const。这样做,它将被允许。

With the Equals call, things are a bit worse. The result of a call to Equals is never considered a compile-time constant (and I don't think it is "optimized" away, for example "same".Equals("same") will actually call the method at run-time). Same thing would happen with (10).Equals(4) or (10).CompareTo(4) > 0 and so on, so strings are not special in this respect.

通过Equals调用,事情会变得更糟。调用Equals的结果永远不会被认为是编译时常量(我不认为它是“优化”的,例如“相同”.Equals(“same”)实际上会在运行时调用该方法)。同样的事情会发生在(10).Equals(4)或(10).CompareTo(4)> 0等等,所以字符串在这方面并不特殊。


Most likely you know already that when

很可能你已经知道什么时候了

short value = cond ? 5 : 10;

is not allowed because cond is not a compile-time constant, you just use the explicit conversion instead, so write:

是不允许的,因为cond不是编译时常量,你只需使用显式转换,所以写:

short value = cond ? (short)5 : (short)10;

or:

要么:

short value = (short)(cond ? 5 : 10);

Technically, they are not identical, since the first one has no narrowing conversion at run-time (the expressions (short)5 and (short)10 are literals of type short), while the last one has to convert an int to short at run-time (which is of course cheaper than incredibly cheap).

从技术上讲,它们并不相同,因为第一个在运行时没有缩小转换(表达式(短)5和(短)10是类型short的文字),而最后一个必须将int转换为short运行时间(当然比便宜得便宜)。


The other (non-deleted!) answers are correct, this is just bonus information.

其他(未删除!)答案是正确的,这只是奖金信息。

#4


2  

The thing is that 10 > 4 ? 5 : 10; is actually converted to a constant at compile time before any type casting is needed. Meaning the compiler realized that the turnary statement can actually be reduced to a constant even before any implicit type casting is required for the compilation. So in other words that expression is the same as:

事情是10> 4? 5:10;在需要任何类型转换之前,实际上在编译时将其转换为常量。这意味着编译器意识到即使在编译需要任何隐式类型转换之前,turnary语句实际上也可以简化为常量。换句话说,表达式与以下内容相同:

value = 5;

In the last two statements, that is not true since you are using a variable to hold the values for you and not a constant. The compiler doesn't check the actual value of the variable to see if it can reduce the expression to a constant. So you actually need the casting.

在最后两个语句中,这是不正确的,因为您使用变量来保存值而不是常量。编译器不检查变量的实际值,以查看它是否可以将表达式减少为常量。所以你实际上需要铸造。

#1


44  

short value;
value = 10 > 4 ? 5 : 10;             //1
value = "test" == "test" ? 5 : 10;   //2
string str = "test";
value = "test" == str ? 5 : 10;      //3
value = "test".Equals(str) ? 5 : 10; //4

The last two ternary expressions (3,4) cannot be resolved to a constant at compile time. Thus the compiler treats the 5 and 10 as int literals, and the type of the entire ternary expression is int. To convert from an int to a short requires an explicit cast.

最后两个三元表达式(3,4)在编译时无法解析为常量。因此编译器将5和10视为int文字,整个三元表达式的类型为int。要从int转换为short,需要显式转换。

The first two ternary expressions (1,2) can be resolved to a constant at compile time. The constant value is an int, but the compiler knows it fits in a short, and thus does not require any casting.

前两个三元表达式(1,2)可以在编译时解析为常量。常量值是一个int,但编译器知道它适合短,因此不需要任何转换。

For fun, try this:

为了好玩,试试这个:

value = "test" == "test" ? 5 : (int)short.MaxValue + 1;

#2


4  

You need a cast to make the two last examples work

你需要一个演员才能使最后两个例子有效

value = (short)("test" == str ? 5 : 10);

Why dont't you need it in the first two?

为什么你不需要在前两个?

Because the first two are compile-time constants. The compiler is able to translate 10 > 4 ? 5 : 10 to true ? 5 : 10, then to just 5

因为前两个是编译时常量。编译器能够翻译10> 4? 5:10为真吗? 5:10,然后到5

So when you write

所以当你写作

value = 10 > 4 ? 5 : 10;

It's effectively the same as

它实际上是一样的

value = 5;

which compiles because the compiler is allowed to implicitly cast constants if they are in the allowed range.

编译是因为如果允许编译器在允许的范围内,则允许隐式转换常量。

Conversely, "test" == str ? 5 : 10; is not a compile time constant, so the compile is not allowed to implcitly cast it. You need to make an explicit cast yoursef.

相反,“测试”== str? 5:10;不是编译时常量,因此不允许编译强制转换它。你需要做一个明确的演员yoursef。

#3


3  

This is defined by the C# Language Specification, of course.

当然,这是由C#语言规范定义的。

The key thing to be aware of is that there are two kinds of conversions from int to short. One is an explicit conversion which always applies but which requires you to write (short) explicitly before the int expression. The other one is an implicit constant expression conversion which only applies when (a) the int expression is a compile-time constant and (b) the value of this compile-time expression is within the range of a short, that is -32768 through 32767.

需要注意的关键是从int到short有两种转换。一种是显式转换,它始终适用但需要您在int表达式之前显式写入(short)。另一个是隐式常量表达式转换,仅当(a)int表达式是编译时常量和(b)此编译时表达式的值在short的范围内时才适用,即-32768到32767。

A literal like 5, 10 or 4 has type int in C# (that goes for any integer literal which is between -2147483648 and 2147483647 and not followed by a symbol L, U or similar). So if we look at the right-hand sides of all your assignments, they are clearly int expressions, not short.

像5,10或4这样的文字在C#中具有int类型(适用于-2147483648和2147483647之间的任何整数文字,并且后面没有符号L,U或类似符号)。因此,如果我们查看所有作业的右侧,它们显然是int表达式,而不是简短的。

In the case 10 > 4 ? 5 : 10, since 10 and 4 are compile-time constants, this is the same as true ? 5 : 10 because the > operator between ints is built-in and will result in a constant when the operands are constants. And in the same way true ? 5 : 10 gives 5 because all three operands are constants, and ?: is classified a constant itself in that case. So it really says:

在10> 4的情况下? 5:10,因为10和4是编译时常量,这是真的吗? 5:10因为int之间的>运算符是内置的,并且当操作数是常量时将导致常量。并以同样的方式真实? 5:10给出5,因为所有三个操作数都是常数,而?:在这种情况下被归类为常数。所以它真的说:

short value = 5;

where the "5" is a compile-time constant. Hence it is checked at compile-time if the int 5 is within the range (it does not matter with the 10, it could be 999999), and since that is the case, the implicit constant expression conversion applies, and it is legal.

其中“5”是编译时常量。因此,在编译时检查int 5是否在范围内(与10无关,它可能是999999),并且由于这种情况,隐式常量表达式转换适用,并且它是合法的。

Note that you can do the same with:

请注意,您可以执行以下操作:

const int huge = 10;
const int tiny = 4;
const int significant = 5;
const int unimporatnt = 10;
short value;
value = huge > tiny ? significant : unimportant;

as long as all the operands are const variables (pun?).

只要所有操作数都是const变量(双关语?)。

Now, if I managed to make the explanation clear, you will also know by now that the obstacle preventing value = "test" == str ? 5 : 10; from working is that you did not mark the str local as const. Do that, and it will be allowed.

现在,如果我设法解释清楚,你现在也知道障碍阻止值=“test”== str? 5:10;从工作是你没有将str local标记为const。这样做,它将被允许。

With the Equals call, things are a bit worse. The result of a call to Equals is never considered a compile-time constant (and I don't think it is "optimized" away, for example "same".Equals("same") will actually call the method at run-time). Same thing would happen with (10).Equals(4) or (10).CompareTo(4) > 0 and so on, so strings are not special in this respect.

通过Equals调用,事情会变得更糟。调用Equals的结果永远不会被认为是编译时常量(我不认为它是“优化”的,例如“相同”.Equals(“same”)实际上会在运行时调用该方法)。同样的事情会发生在(10).Equals(4)或(10).CompareTo(4)> 0等等,所以字符串在这方面并不特殊。


Most likely you know already that when

很可能你已经知道什么时候了

short value = cond ? 5 : 10;

is not allowed because cond is not a compile-time constant, you just use the explicit conversion instead, so write:

是不允许的,因为cond不是编译时常量,你只需使用显式转换,所以写:

short value = cond ? (short)5 : (short)10;

or:

要么:

short value = (short)(cond ? 5 : 10);

Technically, they are not identical, since the first one has no narrowing conversion at run-time (the expressions (short)5 and (short)10 are literals of type short), while the last one has to convert an int to short at run-time (which is of course cheaper than incredibly cheap).

从技术上讲,它们并不相同,因为第一个在运行时没有缩小转换(表达式(短)5和(短)10是类型short的文字),而最后一个必须将int转换为short运行时间(当然比便宜得便宜)。


The other (non-deleted!) answers are correct, this is just bonus information.

其他(未删除!)答案是正确的,这只是奖金信息。

#4


2  

The thing is that 10 > 4 ? 5 : 10; is actually converted to a constant at compile time before any type casting is needed. Meaning the compiler realized that the turnary statement can actually be reduced to a constant even before any implicit type casting is required for the compilation. So in other words that expression is the same as:

事情是10> 4? 5:10;在需要任何类型转换之前,实际上在编译时将其转换为常量。这意味着编译器意识到即使在编译需要任何隐式类型转换之前,turnary语句实际上也可以简化为常量。换句话说,表达式与以下内容相同:

value = 5;

In the last two statements, that is not true since you are using a variable to hold the values for you and not a constant. The compiler doesn't check the actual value of the variable to see if it can reduce the expression to a constant. So you actually need the casting.

在最后两个语句中,这是不正确的,因为您使用变量来保存值而不是常量。编译器不检查变量的实际值,以查看它是否可以将表达式减少为常量。所以你实际上需要铸造。