C#0(负)uint=无符号结果?

C#0(负)uint=无符号结果?,c#,operators,C#,Operators,我希望0和ui在这里都被提升为已签名的long 对于0文本,编译时可以知道转换为uint是安全的 但我想这一切似乎都错了。至少应该发出警告 谢谢 语言规范是否涵盖了这样一种半模糊的情况?为什么要将任何内容提升为long?规范(第7.8.5节)列出了四种整数减法运算符: int运算符-(int x,int y) uint运算符-(uint x,uint y) long运算符-(长x,长y) ulong操作符-(ulong x,ulong y) 假设常量值0可隐式转换为uint,但uint值ui

我希望0和ui在这里都被提升为已签名的long

对于0文本,编译时可以知道转换为uint是安全的

但我想这一切似乎都错了。至少应该发出警告

谢谢


语言规范是否涵盖了这样一种半模糊的情况?

为什么要将任何内容提升为
long
?规范(第7.8.5节)列出了四种整数减法运算符:

  • int运算符-(int x,int y)
  • uint运算符-(uint x,uint y)
  • long运算符-(长x,长y)
  • ulong操作符-(ulong x,ulong y)
假设常量值
0
可隐式转换为
uint
,但
uint
ui
不能隐式转换为
int
,则根据第7.3.4节中描述的二进制运算符重载解析步骤选择第二个运算符

(是否可能您不知道从
0
uint
的隐式常量表达式转换,这是令人困惑的部分?有关详细信息,请参见C#4规范第6.1.9节。)

接下来的第7.3.4节(即第7.3.5节和第7.5.3节)有点曲折,但我认为它定义明确,一点也不含糊

如果是溢出让你烦恼,你会认为这也会失败吗

public void Foo(double d){
    // when called below, d == 2^32-1 
    ...
}
public void Bar(){
    uint ui = 1;
    Foo( 0 - ui );
}

如果没有,这里真正的区别是什么?

是将
int
转换为
uint
以执行0的减法(编译器将其隐式解释为
uint
)。请注意,
int
uint
是一种隐式转换,因此没有警告。你的代码没有问题。。。除了
uint
不是CLS编译器之外。你可以读懂为什么。有关CLS编译器代码的详细信息在选中的上下文中,如果差异超出结果类型的范围,将引发System.OverflowException。在未检查的上下文中,不会报告溢出,并且丢弃结果类型范围之外的任何重要高位

从技术上讲,请执行以下操作:

int x = 10;
int y = int.MaxValue - 5;
int z = x + y;

将导致抛出System.OverflowException,这可能是您所期望的,但根据规范,由于未检查溢出,因此未报告溢出。

此问题等待Jon Skeet:)
int
to
uint
通常不是隐式转换-这是隐式常量表达式转换。参见本规范第6.1.9节。如果我们从
int
变量开始,那么就会升级到
long
。(
int
uint
都可以隐式转换为
long
)@JonSkeet感谢您的澄清:)接受这个答案,因为我困惑的根本原因是零可以隐式转换为uint。基于0是int的假设,我期望提升到long…我认为他的问题更多的是(潜在的)模糊的结果值。i、 如果我从0中减去一个正数,我就不会得到一个正结果。与int示例类似,向正数加10不应导致负数。我想问一个问题,如果你在处理这些类型的数字边界,最好使用
checked
来确保你的结果不含糊(至少对你来说是含糊不清的)@NominSim:这里没有含糊不清的地方。它的行为完全符合规范要求。如果OP想要使用检查过的上下文,那么他们绝对可以,但是这里不需要警告,而且它的行为都是正确的。我相信OP的实际问题是它是用
uint
算法执行的,而他希望它使用
long
算法:“我希望0和ui都在这里被提升为带符号的long。”我知道它的行为完全符合规范的要求,模糊性不在规范中,而是在动作a中。如果我从负数中减去一个保证的正数,我应该得到一个负数。这就是为什么我认为OP在处理可能超出特定数据结构界限的数字时应该使用检查上下文的原因。@NominSim:你知道这是按照规范的,但我不相信OP这样做了。我不认为“歧义”这个词在这里有用——根本没有任何意义。可能会有意外或不受欢迎的行为,但这与含糊不清不同。没错,我使用这个词是因为OP使用了它。现在我想得更多了,他说“至少应该发出警告”一开始对我来说似乎是合理的,但我想得越多,我就越同意你的看法,那就是一切都很好,握手只能让你走到目前为止。。。
double d = checked(0-ui);