为什么在强制转换运算符中将 double 隐式转换为 int?

Why is double implicitly converted to int in a cast operator?

提问人:Dave Cousineau 提问时间:7/17/2023 更新时间:7/17/2023 访问量:84

问:

这是我以前没有注意到的奇怪行为。我预计无法从 a 强制转换,但该值被隐式转换为 an,我默默地丢失了小数部分。我真的不能在不从 s 转换的情况下从 s 转换吗?doubledoubleintintdouble

readonly struct TestDecimal {
   public decimal Value { get; }

   TestDecimal(decimal value) => 
      Value = value;

   public static explicit operator TestDecimal(int x) => new(x);
}

...

// these assertions fail, but really this shouldn't even compile
[TestMethod]
public void Test_CastFromDouble() {
   var value = (TestDecimal)12.34; // shouldn't compile
   Assert.AreEqual(12.34m, value.Value); // assertion failed, actual value: 12.0m
}

[TestMethod]
public void Test_CastFromDecimal() {
   var value = (TestDecimal)12.34m; // shouldn't compile
   Assert.AreEqual(12.34m, value.Value); // assertion failed, actual value: 12.0m
}
C# .NET-6.0 C#-10.0

评论

0赞 Sweeper 7/17/2023
@Dai我无法重现。IL说。夏普实验室ldc.i4.s 12
0赞 Dai 7/17/2023
@Sweeper我正在使用 Linqpad,并且我得到了相同的指令。请记住,这是 / / 操作数:learn.microsoft.com/en-us/dotnet/api/...ldc.i4.slcd.i4.sint8u8byte
0赞 Dai 7/17/2023
另外:stackoverflow.com/questions/6755178/......
0赞 Sweeper 7/17/2023
@Dai 是什么类型,肯定是实现细节吗?12
0赞 Dai 7/17/2023
键入为 。12int8

答:

2赞 Sweeper 7/17/2023 #1

这是因为标准转换可以作为用户定义转换的一部分进行。在用户定义的转换之前,可以进行标准转换,将表达式的类型转换为转换运算符所需的类型。还可以进行另一种标准转换,将转换运算符的返回值转换为该上下文中预期的任何类型。

§10.5.3 用户定义转换的评估

一旦最具体的用户定义转换运算符 识别后,实际执行用户自定义转换 最多涉及三个步骤:

  • 首先,如果需要,执行从源表达式到用户定义或提升的操作数类型的标准转换 转换运算符。
  • 接下来,调用用户定义或提升的转换运算符来执行转换。
  • 最后,如果需要,执行从用户定义的转换运算符的结果类型到目标的标准转换 类型。

然后,本节继续定义诸如最包含类型的术语,然后在 §10.5.5 中使用这些术语来描述如何准确解决这些转换。

对于您的案例来说,最重要的是,标准的显式转换包括“ to ”和“ to ”。这使您能够使用 / 作为参数调用转换运算符。请参阅语言规范部分:doubleintdecimalintdoubledecimal

§10.4.3

标准显式转换都是标准隐式转换 转化次数加上显式转化的子集,其中 存在相反的标准隐式转换。

“到”和“到”都是“存在相反标准隐式转换的显式转换”。doubleintdecimalint

§10.3.2 显式数字转换

  • ...
  • 从 到 、 、 、doublesbytebyteshortushortintuintlongulongcharfloatdouble
  • 从 到 、 、 、decimalsbytebyteshortushortintuintlongulongcharfloatdouble
  • ...

§10.4.2

以下隐式转换被归类为标准隐式转换 转换:

  • ...
  • 隐式数字转换 (§10.2.3)

§10.2.3

隐式数值转换包括:

  • ...
  • 从 到 、 、 或 。intlongfloatdoubledecimal
  • ...

评论

0赞 Dai 7/17/2023
链接的文章描述的是 - 和 - 但不是 。doubleintintdecimaldecimalint
0赞 Sweeper 7/17/2023
@Dai 对不起,我忘记了问题中的第二个例子,引号有点不完整。现在应该修复它。
0赞 Dave Cousineau 7/17/2023
我怀疑是这样的,但可以使用显式转换似乎是错误的。