Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler implicitly convert a double to int when an explicit user-defined operator exists from int to Foo?

Why is an explicit conversion from double to Foo possible, even though Foo only defined an explicit conversion from int to Foo?

Why is in my case double implicitly converted to an int?

using System;

class Program
{
    static void Main(string[] args)
    {
        double doub = 15.7;
        Foo foo = (Foo)doub;
        Console.WriteLine(foo.value); //writes "15"
    }
}

struct Foo
{
    public int value;
    public static explicit operator Foo(int val) //no matter if implicit
    {
        return new Foo { value = val };
    }
}
like image 811
Alex78191 Avatar asked Feb 28 '16 23:02

Alex78191


1 Answers

I believe this is layed out in section 6.4.3 of the C# 5 Language Specification.

A first hint is given in section 6.2.8 User Defined explicit conversions (emphasis mine):

A user-defined explicit conversion consists of an optional standard explicit conversion, followed by execution of a user-defined implicit or explicit conversion operator, followed by another optional standard explicit conversion

Notice how not one but potentially three conversions occur.

Now, to know what is a 'standard explicit conversion' we have to look at section 6.2.3 Standard explicit conversions:

The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. In other words, if a standard implicit conversion exists from a type A to a type B, then a standard explicit conversion exists from type A to type B and from type B to type A.

And looking back at section 6.3.1 Standard implicit conversions we can see that this is a part of it:

  • Implicit numeric conversions (§6.1.2)

In other words: an explicit numeric conversion (like double -> int) can be applied before the user-defined conversion.

If we now look at 6.4.3 Evaluation of user-defined conversions we see the following (emphasis mine):

First, if required, performing a standard conversion from the source type to the operand type of the userdefined 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 or lifted conversion operator to the target type.

Which is exactly what happens in your scenario.

like image 155
Jeroen Vannevel Avatar answered Sep 18 '22 22:09

Jeroen Vannevel