你可以在sbyte和byte,int,uint,short,ushort,long,double和float之间进行>,<,==等比较。但不是ulong。
我的大脑爆炸了。任何人都可以解释为什么sbyte可以与uint进行比较,但不 ulong?
public bool sbyte_ulong_compare(sbyte x, ulong y)
{
return x < y; // compiler error CS0019
}
此外,使用unchecked
并不能让事情变得更好。大脑融化。
另一个编辑。这有效:
public bool sbyte_ulong_compare(sbyte x, ulong y)
{
//
// returns x < y
//
if (x < 0)
return true;
if (y > 127)
return true;
return ((long)x < (long)y);
}
答案 0 :(得分:20)
正确的推理如下。
规范声明:
对于x op y形式的操作, 其中op是比较运算符, 重载分辨率是 用于选择特定的运算符 实施
好的,重载决策必须使用的运算符实现是什么?他们是:
bool operator <(int x, int y);
bool operator <(uint x, uint y);
bool operator <(long x, long y);
bool operator <(ulong x, ulong y);
bool operator <(float x, float y);
bool operator <(double x, double y);
bool operator <(decimal x, decimal y);
对于所有枚举类型,加上enum less-than运算符,以及前述每个类型的提升到可空版本。
重载分辨率必须首先消除不适用的运算符,然后从剩余的适用运算符集中确定 best 运算符。
int,uint,long和enum运算符(及其提升的形式)都被删除了,因为ulong不会隐式转换为那些类型。
uint和ulong运算符(以及它们提升的形式)都被删除了,因为sbyte不会隐式转换为那些类型。
离开
bool operator <(float x, float y);
bool operator <(double x, double y);
bool operator <(decimal x, decimal y);
和他们提升的形式。我们现在必须从这六个中确定 best 运算符。
“最佳”是什么意思?比较两个运算符时,具有更具体的操作数类型的运算符更好。 “更具体”是指“老虎”比“动物”更具体,因为所有老虎都可以转换为动物但不是所有动物都可以转换为老虎。
显然,未提升的形式优于所有相应的提升形式。非可空类型比其对应的可空类型更具体,因为非可空类型总是可转换为其可空类型,但反之亦然。我们可以消除提升的形式。
留下三个。这三个中哪一个是最好的?
浮动比双重更具体。每个浮动都可以转换为double,但不是每个double都可以转换为float。因此消除了双倍。剩下两个。
bool operator <(float x, float y);
bool operator <(decimal x, decimal y);
哪一项最好?没有从float到decimal的隐式转换。没有从decimal到float的隐式转换。因此,两者都不比另一个好。
因此无法确定最佳操作员。重载解析失败。
我们已经决定报告一个通用的错误消息,只是说没有这样的运算符可以做你想要的,而不是给出看似奇怪和混乱的错误消息“运算符重载决策失败,因为浮动既不好也不差十进制”。我认为这是一个合理的设计选择。
答案 1 :(得分:7)
当比较不同整数类型的两个整数时,操作的类型是可以表示两个操作数组合的全部范围的最小整数类型。如果将带符号的字节与uint进行比较,则操作的类型很长,因为long有足够的范围来覆盖有符号字节的负部分和uint的正部分。
当您尝试比较sbyte和ulong时,没有整数类型可以跨越ulong和signed byte的负部分的范围。编译器仅考虑内置整数类型。不包括隐式提升为Decimal,因为Decimal不是整数类型,并且出于性能原因。
在第二个代码示例中,由于您已对操作数进行了预先限定,因此可以安全地将操作数类型转换为不跨越两个操作数范围的公共整数类型。另请注意,在第二个示例中,您可以对字节(而不是长)进行类型转换而不会丢失信息,因为您已经确定ulong值小于127且sbyte值为非负值。
C#编译器没有“看到”您已经对操作数进行了资格预审,并且逻辑上操作数中的值都在字节范围内,并且编译器本身不生成执行此类预审的代码。
某些语言会发出类似于您的第二个示例的资格预审代码,以支持不具有公共超集类型的类型之间的比较。你为此获得了性能和内存(代码大小)。 C#可能不会在不想“奖励”不良编码实践的精神下发出这种预审资格代码。如果您要比较签名值和ulong,您需要了解并承担费用。
在语言理论中,有一个类型推理的分支,称为(我认为)类型代数,它跟踪变量的测试并动态地缩小变量类型的范围,因为在代码流中发现了新的约束。这种类型的推理形式允许您在第二个示例中比较操作数而不进行类型转换,因为它会看到您已将操作数预先限定为字节范围。 C#不进行这种类型的推理。我认为Haskell或F#可能。