为什么C#发出错误“不能隐式地将int转换为ushort”而不是ushorts上的模运算?

问题描述 投票:5回答:2

在另一个帖子中,有人询问为什么在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),所以没有溢出到整数的风险。那我为什么会收到这个错误呢?

c# integer-overflow
2个回答
7
投票

正在使用的%运算符,即使使用shortsushorts,也有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.

1
投票

这是因为%算子没有为小于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然后默认为上面列表中的第一个重载,它返回一个无法隐式地强制转换为intushort


如果你问为什么它没有定义,你可能不得不问C#规范的创建者。

© www.soinside.com 2019 - 2024. All rights reserved.