在另一个帖子中,有人询问为什么在C#中添加两个ushort
值引发错误。例如
ushort x = 4;
ushort y = 23;
ushort z = x+y; // ERROR cannot implicitly convert int to ushort
在该线程中,人们认为plus + operater默认采用两个整数,这是一种语言特性,有助于避免算术溢出。但是我在以下函数中遇到了同样的错误:
public RGB(ushort red, ushort green, ushort blue)
{
// this class RGB has three ushort fields: r, g, and b
r = red % ((ushort)256);
g = green % ((ushort)256);
b = blue % ((ushort)256);
}
编译器出错的地方并说“不能隐式地将类型'int'转换为'ushort'。存在显式转换......”。但是这里模数%运算符防止溢出的论点根本没有任何意义:如果x和y是ushort
值,那么x%y < max(x,y)
,所以没有溢出到整数的风险。那我为什么会收到这个错误呢?
正在使用的%运算符,即使使用shorts
或ushorts
,也有int %(int a, int b)
的签名。所以你的短裤被提升为整数,你的结果是你试图分配给ushort
的整数,这是一个有损的演员,所以你需要明确。
考虑一下:
ushort x = 5;
ushort y = 6;
var res = x % y;
Console.WriteLine(res.GetType()); // System.Int32
ushort z = res; // cast error, explicit conversion exists
ushort zz = (ushort)res; // Fine, we cast down.
这是因为%
算子没有为小于int
的整数类型定义。 C#规范列出了在整数类型上为模运算符定义的所有重载:
int operator %(int x, int y);
uint operator %(uint x, uint y);
long operator %(long x, long y);
ulong operator %(ulong x, ulong y);
https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#remainder-operator
使用%
on ushorts然后默认为上面列表中的第一个重载,它返回一个无法隐式地强制转换为int
的ushort
。
如果你问为什么它没有定义,你可能不得不问C#规范的创建者。