The reason the explicit conversion succeeded in the original case was
because there was a standard conversion from double to int. There are two
categories of conversions, standard and user-defined. Standard conversions
are defined by C# and user-defined conversions are the conversion operators
that you add to your types. In my explanation, I introduce the notion of a
'single conversion operation', for which there is not an official
definition. However, I use the term for the purpose of explanation because
I feel it is central to identifying the problem and the work around. Here's
a short overview of how the conversion process works (a single conversion
operation):
1. Perform a standard conversion, if necessary, to the parameter type of an
available user-defined conversion.
2. Perform the user-defined conversion that matches a type after a standard
conversion occurs or with whatever type matched without a standard
conversion.
3. Perform a standard conversion from the results of the user-defined
conversion to the target type of the conversion.
Notice #2 where there is exactly one "user-defined" conversion. The
original case succeeded because there was 1) a standard explicit conversion
from double to int, 2) a user-defined conversion from int to Test, and 3) a
standard conversion was not required because the conversion operator used
already returned the target type specified.
Now, notice how the case with your user-defined types and user-defined
conversions is structured. Here you are trying to perform 1) a user-defined
conversion from MyDouble to MyInt, 2) a user-defined conversion from MyInt
to Test, and <kaboom> you won't get to 3 because C# will detect that what
you are doing is illegal and generate a compiler error. You are not allowed
to perform two or more user-defined conversions in a single conversion
operation. In other words, you can only have one user-defined conversion in
any single conversion operation.
Here's how to fix it:
Test t = (Test)(MyInt)d;
This performs a single user-defined conversion from MyDouble to MyInt, which
is a single conversion operation. Then it performs a user-defined
conversion from MyInt to Test, which is another single conversion operation.
On another note, for those of you who are enjoying my grammar mistakes in
this thread, please forgive any further transgressions. In particular, I
have been unable to identify the correct spelling of <kaboom>. <grin>
Joe
--
http://www.csharp-station.com
"Steve Gough" <st*************@hotmail.com> wrote in message
news:4a**************************@posting.google.c om...
"Joe Mayo" <jm***@nospamAtCSharpDashStation.com> wrote in message
news:<#V**************@tk2msftngp13.phx.gbl>...
per the built-in types I've created an implicit conversion from MyInt
to MyDouble and an explicit conversion from MyDouble to MyInt. Based
on the earlier example and on Joe's explanation I had expected to see
a silent conversion from MyDouble to MyInt, and then from MyInt to
Test. What I actually get is the error that I originally expected to
get in the first example; namely, the explicit conversion from
MyDouble to Test is not possible.
class Test
{
public static implicit operator Test(MyInt i)
{
return new Test();
}
}
struct MyInt
{
public static implicit operator MyDouble(MyInt i)
{
return new MyDouble();
}
}
struct MyDouble
{
public static explicit operator MyInt(MyDouble d)
{
return new MyInt();
}
}
class Driver
{
public static void Main()
{
MyDouble d = new MyDouble();
//Test t = d; // error, as expected.
//Test t = (Test)d; // error for MyDouble/MyInt; why not for
double/int?
}
}