条件运算符不能隐式转换?

发布于 2024-08-20 04:20:07 字数 461 浏览 9 评论 0原文

我对 C# 的这个小怪癖有点困惑:

给定变量:

Boolean aBoolValue;
Byte aByteValue;

以下编译:

if (aBoolValue) 
    aByteValue = 1; 
else 
    aByteValue = 0;

但这不会:

aByteValue = aBoolValue ? 1 : 0;

错误说:“无法将类型‘int’隐式转换为‘byte’。”

当然,这个怪物会编译:

aByteValue = aBoolValue ? (byte)1 : (byte)0;

这里发生了什么事?

编辑:

使用 VS2008,C# 3.5

I'm a little stumped by this little C# quirk:

Given variables:

Boolean aBoolValue;
Byte aByteValue;

The following compiles:

if (aBoolValue) 
    aByteValue = 1; 
else 
    aByteValue = 0;

But this will not:

aByteValue = aBoolValue ? 1 : 0;

Error says: "Cannot implicitly convert type 'int' to 'byte'."

And of course, this monstrosity will compile:

aByteValue = aBoolValue ? (byte)1 : (byte)0;

What's going on here?

EDIT:

Using VS2008, C# 3.5

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

楠木可依 2024-08-27 04:20:07

这是一个相当常见的问题。

在 C# 中,我们几乎总是从内到外进行推理。当你看到

x = y;

我们计算出x的类型是什么,y的类型是什么,以及y的类型是否与x的赋值兼容。但是当我们计算 y 的类型时,我们并没有使用我们知道 x 的类型这一事实。

这是因为可能有多个 x:

void M(int x) { }
void M(string x) { }
...
M(y); // y is assigned to either int x or string x depending on the type of y

我们需要能够在知道表达式被分配给什么的情况下计算出它的类型。类型信息从表达式流出,而不是流入表达式。

为了计算出条件表达式的类型,我们计算出结果和替代表达式的类型,选择两种类型中更通用的一个,这将成为条件表达式的类型。因此,在您的示例中,条件表达式的类型是“int”,并且它不是常量(除非条件表达式为常量 true 或常量 false)。由于它不是常量,因此不能将其分配给 byte;当结果不是常量时,编译器仅根据类型而不是值进行推理。

所有这些规则的例外是 lambda 表达式,其中类型信息确实从上下文流入 lambda。获得正确的逻辑非常困难。

This is a fairly frequently asked question.

In C#, we almost always reason from inside to outside. When you see

x = y;

we work out what is the type of x, what is the type of y, and whether the type of y is assignment compatible with x. But we do not use the fact that we know what the type of x is when we are working out the type of y.

That's because there might be more than one x:

void M(int x) { }
void M(string x) { }
...
M(y); // y is assigned to either int x or string x depending on the type of y

We need to be able to work out the type of an expression without knowing what it is being assigned to. Type information flows out of an expression, not into an expression.

To work out the type of the conditional expression, we work out the type of the consequence and the alternative expressions, pick the more general of the two types, and that becomes the type of the conditional expression. So in your example, the type of the conditional expression is "int", and it is not a constant (unless the condition expression is constant true or constant false). Since it is not a constant, you can't assign it to byte; the compiler reasons solely from the types, not from the values, when the result is not a constant.

The exception to all these rules is lambda expressions, where type information does flow from the context into the lambda. Getting that logic right was very difficult.

纸伞微斜 2024-08-27 04:20:07

我正在使用 VS 2005, for 并且我可以重现, for bool &布尔值,但不是 true

 bool abool = true;
 Boolean aboolean = true;
 Byte by1 = (abool ? 1 : 2);    //Cannot implicitly convert type 'int' to 'byte'
 Byte by2 = (aboolean ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte'
 Byte by3 = (true ? 1 : 2);     //Warning: unreachable code ;)

最简单的解决方法似乎是这种强制转换

 Byte by1 = (Byte)(aboolean ? 1 : 2);

所以,是的,三元运算符似乎导致常量将其类型“固定”为整数,并禁用隐式类型转换,否则您将从常量中获得隐式类型转换适合较小的类型。

I'm using VS 2005, for and I can reproduce, for bool & Boolean, but not for true

 bool abool = true;
 Boolean aboolean = true;
 Byte by1 = (abool ? 1 : 2);    //Cannot implicitly convert type 'int' to 'byte'
 Byte by2 = (aboolean ? 1 : 2); //Cannot implicitly convert type 'int' to 'byte'
 Byte by3 = (true ? 1 : 2);     //Warning: unreachable code ;)

The simplest workaround seems to be this cast

 Byte by1 = (Byte)(aboolean ? 1 : 2);

So, yes, it seems that the ternary operator is causing the constants to "fix" their types as ints and disable the implicit type conversion that you would otherwise get from constants that fit within the smaller type.

漆黑的白昼 2024-08-27 04:20:07

我可能没有一个很好的答案给你,但如果你在很多地方这样做,你可以声明:

private static readonly Byte valueZero = (byte)0;
private static readonly Byte valueOne = (byte)1;

以及这些变量。如果 const 是项目本地的,那么您可能不会使用它。

编辑:使用readonly是没有意义的 - 这些并不意味着要改变。

I may not have a great answer for you, but if you do this in many places, you could declare:

private static readonly Byte valueZero = (byte)0;
private static readonly Byte valueOne = (byte)1;

and just these variables. You might get away with using const if it is local to the project.

EDIT: using readonly would not make sense - these aren't ever meant to change.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文