Explicit conversion from SomeType* to IntPtr

A

Alex Sedow

Why explicit conversion from SomeType* to IntPtr is not ambiguous (according
to standart)?

Example:

// System.IntPtr
class IntPtr
{
public static explicit System.IntPtr (int);
public static explicit System.IntPtr (long);
public static explicit System.IntPtr (void*);
}

struct SomeType {}

unsafe void f ( SomeType *p )
{
if ( (IntPtr)p == IntPtr.Zero ) // <-
{
// ...
}
}

Above example contain explicit conversion from SomeType* to IntPtr. The
question is how C# compiler select explicit conversion. Standart say: "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." There are 3 user-defined exlicit conversions. Conversion
System.IntPtr (int) is removing from list because long is more encompassing
type than int (13.4.2). But neither of two remaining types is more
encompassing than other.

SomeType *p -> long -> IntPtr (explicit+user-defined explicit conversion)
SomeType *p -> void* -> IntPtr (implicit+user-defined explicit conversion)

If neither of two conversions is better than conversion is ambiguos. But
compiler think that conversion with through void* is better. Why? I not
found where standart say that implicit conversion is better than explicit
conversion.

Questions:
1. Is conversion from void* to IntPtr is processed as user-defined?
2. Why conversion sequence (System.IntPtr)(void*(p)) is better than
(System.IntPtr)(long(p))?

Any suggestions.

Alex.
 
D

Daniel O'Connell [C# MVP]

SomeType *p -> long -> IntPtr (explicit+user-defined explicit conversion)
SomeType *p -> void* -> IntPtr (implicit+user-defined explicit conversion)

If neither of two conversions is better than conversion is ambiguos. But
compiler think that conversion with through void* is better. Why? I not
found where standart say that implicit conversion is better than explicit
conversion.

Questions:
1. Is conversion from void* to IntPtr is processed as user-defined?

I believe so
2. Why conversion sequence (System.IntPtr)(void*(p)) is better than
(System.IntPtr)(long(p))?

in section 25.4, a standard implicit conversion is defined for any
pointer-type to void*

"1 Finally, in an unsafe context, the set of standard implicit conversions
(§13.3.1) includes the following pointer conversion:
2 From any pointer-type to the type void*. "

and then section 13.4.2 says
" If a standard implicit conversion (§13.3.1) exists from a type A to a type
B, and if neither A nor B are interface-types, then A is said to be
encompassed by B, and B is said to encompass A. "

So, according to the spec, void* encompasses SomeType*. Conversions to long
and int are not standard implicit conversions and therefore would not
encompass SomeType*

Now, 13.4.4 says
"Otherwise, if any of the operators in U convert from types that encompass
S, then SX is the most encompassed type in the combined set of source types
of those operators. 10 If no most encompassed type can be found, then the
conversion is ambiguous and a compile-time error occurs. "

Out of the types int, long, and void*, only void* encompasses SomeType* and
therefore the set of types is reduced to strictly void* and therefore the
most encompassed type is void*. And because it is the most encompassed type,
SX becomes void* and when you follow the rules you mentioned above and no
explicit conversion occurs because there is a user defined conversion that
goes from SX to TX as defined, again, in 13.4.4:

"If U contains exactly one user-defined conversion operator that converts
from SX to TX, then this is the most specific conversion operator."

So, the best path is SomeType* -> void* -> IntPtr::explicit
IntPtr(void*) ->IntPtr
 
A

Alex Sedow

Now, 13.4.4 says
"Otherwise, if any of the operators in U convert from types that encompass
S, then SX is the most encompassed type in the combined set of source types
of those operators. 10 If no most encompassed type can be found, then the
conversion is ambiguous and a compile-time error occurs. "

I miss that. In other words - if standart implicit conversion from S to Sx
exist than compiler select best implicit conversion. Otherwise compiler
tryed to select some best standart explicit conversion.

Thank you Daniel!

Alex.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top