我ulong用一个私有数据成员编写了一个简单的包装器.我希望能够将包装器转换ulong为检索数据.我希望强制转换uint和丢失数据是非法的,所以我没有写一个显式的强制转换uint.当C#允许我uint毫无怨言地投射并且即使高位丢失也没有抛出异常时,你可以想象我的惊喜.
这是我的测试代码:
class Program {
static void Main(string[] args) {
ULongWrapper a = new ULongWrapper(0xfffffffffUL);
ulong b = (ulong)a;
uint c = (uint)a;
Console.WriteLine("{0:x}", b);
Console.WriteLine("{0:x}", c);
}
}
class ULongWrapper {
private ulong data;
public ULongWrapper(ulong data) {
this.data = data;
}
public static explicit operator ulong(ULongWrapper x) {
return x.data;
}
}
Run Code Online (Sandbox Code Playgroud)
哪个印刷品:
fffffffff
ffffffff
Run Code Online (Sandbox Code Playgroud)
这似乎是不需要的行为,因为我希望强制转换uint在编译时失败!编译器使用ulong显式转换运算符,然后以某种方式隐式地将该结果转换为uint无边界检查.这是C#中的错误,如果没有,为什么?
Eri*_*ert 13
这是C#中的错误吗?
没有.
为什么不?
因为此处演示的行为与规范一致.仔细阅读规范的6.4.4和6.4.5节.(请注意,C#编译器有许多方法与规范的这一部分不一致;实现在不明确的极端情况下有许多错误,特别是涉及提升的运算符.)
我希望转换为uint并丢失数据是非法的.
不幸的是,你无法总是得到你想要的东西.
当C#允许我毫无怨言地投射到uint并且即使高位丢失也没有抛出异常时,你可以想象我的惊讶.
我同意,这有点令人惊讶.
规则是:允许每个用户定义的转换在输入和输出上都插入标准转换.此外,如果它是显式转换 - 也就是说,您正在进行转换 - 那么插入的标准转换可以是隐式或显式标准转换.(事实上,强制转换可能会导致显式标准转换插入到用户定义的隐式转换中!)
在您的情况下,存在从ULongWrapper到ulong的显式用户定义转换,以及从ulong到uint的标准显式转换.因此,将ULongWrapper转换为uint是合法的.
您可能会考虑不首先实现显式转换,因为显然您不喜欢显式转换的语义.只需编写一个返回底层ulong的方法或属性,并完成它.