English 中文(简体)
Why is double implicitly converted to int in a cast operator?
原标题:

This is strange behaviour that I haven t noticed before. I expected not to be able to cast from a double but instead the double value is implicitly converted to an int and I silently lose the fractional portion. Can I really not convert from ints without also converting from doubles?

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
}
问题回答

This is because standard conversions can occur as part of a user-defined conversion. Before your user-defined conversion, there can be a standard conversion converting the expression s type to the type your conversion operator expects. There can also be another standard conversion converting the return value of your conversion operator to whatever type is expected in that context.

§10.5.3 Evaluation of user-defined conversions

Once a most-specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • First, if required, performing a standard conversion from the source expression to the operand type of the user-defined or lifted conversion operator.
  • Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • Finally, if required, performing a standard conversion from the result type of the user-defined conversion operator to the target type.

The standard explicit conversions includes "from double to int" and "from decimal to int". See the language spec sections:

§10.4.3:

The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists.

Both "double to int" and "decimal to int" are "explicit conversions for which an opposite standard implicit conversion exists".

§10.3.2 Explicit numeric conversions:

  • ...
  • From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.
  • From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.
  • ...

§10.4.2

The following implicit conversions are classified as standard implicit conversions:

  • ...
  • Implicit numeric conversions (§10.2.3)

§10.2.3:

The implicit numeric conversions are:

  • ...
  • From int to long, float, double, or decimal.
  • ...




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签