A conversion operator declaration introduces a user-defined conversion (§13.
4), which augments the predefined
implicit and explicit conversions.
A conversion operator declaration that includes the implicit keyword
introduces a user-defined implicit
conversion. Implicit conversions can occur in a variety of situations,
including function member invocations, cast
expressions, and assignments. This is described further in §13.1.
Chapter 17 Classes
257
A conversion operator declaration that includes the explicit keyword
introduces a user-defined explicit
conversion. Explicit conversions can occur in cast expressions, and are
described further in §13.2.
A conversion operator converts from a source type, indicated by the
parameter type of the conversion operator, to
a target type, indicated by the return type of the conversion operator. A
class or struct is permitted to declare a
conversion from a source type S to a target type T provided all of the
following are true:
? S and T are different types.
? Either S or T is the class or struct type in which the operator
declaration takes place.
? Neither S nor T is object or an interface-type.
? T is not a base class of S, and S is not a base class of T.
From the second rule it follows that a conversion operator must convert
either to or from the class or struct type
in which the operator is declared. [Example: For example, it is possible
for a class or struct type C to define a
conversion from C to int and from int to C, but not from int to bool. end
example]
It is not possible to redefine a pre-defined conversion. Thus, conversion
operators are not allowed to convert from
or to object because implicit and explicit conversions already exist
between object and all other types.
Likewise, neither the source nor the target types of a conversion can be a
base type of the other, since a
conversion would then already exist.
User-defined conversions are not allowed to convert from or to
interface-types. In particular, this restriction
ensures that no user-defined transformations occur when converting to an
interface-type, and that a conversion to
an interface-type succeeds only if the object being converted actually
implements the specified interface-type.
The signature of a conversion operator consists of the source type and the
target type. (This is the only form of
member for which the return type participates in the signature.) The
implicit or explicit classification of a
conversion operator is not part of the operator?s signature. Thus, a class
or struct cannot declare both an
implicit and an explicit conversion operator with the same source and
target types.
[Note: In general, user-defined implicit conversions should be designed to
never throw exceptions and never lose
information. If a user-defined conversion can give rise to exceptions (for
example, because the source argument
is out of range) or loss of information (such as discarding high-order
bits), then that conversion should be defined
as an explicit conversion. end note]
[Example: In the example
using System;
public struct Digit
{
byte value;
public Digit(byte value) {
if (value < 0 || value > 9) throw new ArgumentException();
this.value = value;
}
public static implicit operator byte(Digit d) {
return d.value;
}
public static explicit operator Digit(byte b) {
return new Digit(b);
}
}
the conversion from Digit to byte is implicit because it never throws
exceptions or loses information, but the
conversion from byte to Digit is explicit since Digit can only represent a
subset of the possible values of a
byte. end example]