I’m just replying to the first part of the question to start with. (I suggest that the second part should be a separate question; it’s more likely to be a bug.)
There’s only an explicit conversion from decimal
to int
, but that conversion is being implicitly called in your code. The conversion happens in this IL:
IL_0010: stloc.0
IL_0011: ldloc.0
IL_0012: call int32 [mscorlib]System.Decimal::op_Explicit(valuetype [mscorlib]System.Decimal)
IL_0017: call valuetype NumberFixedPoint2 NumberFixedPoint2::op_Implicit(int32)
I believe this is the correct behaviour according to the spec, even though it’s surprising1. Let’s work our way through section 6.4.5 of the C# 4 spec (User-Defined Explicit Conversions). I’m not going to copy out all the text, as it would be tedious – just what the relevant results are in our case. Likewise I’m not going to use subscripts, as they don’t work well with code font here 🙂
- Determine the types
S0
andT0
:S0
isdecimal
, andT0
isNumberFixedPoint2
. - Find the set of types,
D
, from which used-defined conversion operators will be considered: just{ decimal, NumberFixedPoint2 }
- Find the set of applicable user-defined and lifted conversion operators,
U
.decimal
encompassesint
(section 6.4.3) because there’s a standard implicit conversion fromint
todecimal
. So the explicit conversion operator is inU
, and is indeed the only member ofU
- Find the most specific source type,
Sx
, of the operators inU
- The operator doesn’t convert from
S
(decimal
) so the first bullet is out - The operator doesn’t convert from a type that encompasses
S
(decimal
encompassesint
, not the other way round) so the second bullet is out - That just leaves the third bullet, which talks about the “most encompassing type” – well, we’ve only got one type, so that’s okay:
Sx
isint
.
- The operator doesn’t convert from
- Find the most specific target type,
Tx
, of the operators inU
- The operator convers straight to
NumberFixedPoint2
soTx
isNumberFixedPoint2
.
- The operator convers straight to
- Find the most specific conversion operator:
U
contains exactly one operator, which does indeed convert fromSx
toTx
, so that’s the most specific operator
- Finally, apply the conversion:
- If
S
is notSx
, then a standard explicit conversion fromS
toSx
is performed. (So that’sdecimal
toint
.) - The most specific user-defined conversion operator is invoked (your operator)
T
isTx
so there’s no need for the conversion in the third bullet
- If
The line in bold is the bit which confirms that a standard explicit conversion really is feasible, when only an explicit conversion from a different type is actually specified.
1 Well I found it surprising, at least. I’m not aware of seeing this before.