Consider the following code:
class Program
{
public static explicit operator long(Program x) { return 47; }
static int Main(string[] args)
{
var x = new Program();
Console.WriteLine((decimal) x);
}
}
To my surprise, this outputs 47; in other words, the explicit operator long is called even though the cast is to decimal.
Is there something in the C# spec that explicitly says that this should happen (if so, where exactly) or is this the result of some other rule(s) I’m missing?
I’ve found the answer. First of all, there is the concept of one type being encompassed by another, which is defined in 6.4.3 Evaluation of user-defined conversions as follows:
6.3.1 Standard implicit conversions states that “Implicit numeric conversions (§6.1.2)” are a standard implicit conversion, and 6.1.2 Implicit numeric conversions in turn defines an implicit conversion from
longtodecimal. Therefore,longis encompassed bydecimal.Next, 6.4.5 User-defined explicit conversions states that one of the stages in determining whether an explicit conversion is applicable is to:
Here,
Drefers to the result of an earlier step which, in this case, contains onlydecimal,Programandobject. Thus, the setUwill contain theProgram-to-longexplicit operator I declared becauselongis encompassed bydecimal(as we found earlier).One of the next steps selects
longas the most specific target type,TX.Finally, the last step in that same algorithm states:
Here,
SandSXare bothProgram, so the first part does nothing.TXwas selected to belongandTis the target type,decimal, so the last part executes the standard conversion fromlongtodecimal.