Beachten Sie zuerst, dass C# maximal eine implizite benutzerdefinierte Konvertierung zwischen Typen erlaubt.
Also, wenn Sie zwei Instanzen von vergleichen zu können, sieht der Compiler, dass es eine benutzerdefinierte implizite Konvertierung ein zu einem double
mit dem umwandeln können zu vergleichen.
Wenn Sie jedoch zwei Instanzen von Duration
vergleichen, kann der Compiler keine einfache implizite Konvertierung finden, die es verwenden kann, um den Vergleich zu ermöglichen. Der Compiler berücksichtigt keine benutzerdefinierten Vergleichsoperatoren für die Typen, auf die der Typ implizit konvertiert werden kann. Es sucht nur nach integrierten Vergleichsoperatoren für die Typen, auf die der Typ implizit konvertiert werden kann.
Daher wird der Compiler nicht die implizite Konvertierung zu TimeSpan
verwenden, obwohl TimeSpan
einen benutzerdefinierten Vergleichsoperator bietet, der theoretisch verwendet werden könnte.
Auch wenn die TimeSpan
Klasse eine implizite Konvertierung zu double
lieferte, würde der Compiler sie immer noch nicht verwenden, da sie höchstens eine implizite benutzerdefinierte Konvertierung in der Kette der impliziten Konvertierungen berücksichtigt.
Mit anderen Worten, da diese Strukturen:
public struct Number
{
public readonly double Value;
public Number(double value)
{
Value = value;
}
public static implicit operator Number(double duration)
{
return new Number(duration);
}
public static implicit operator double(Number number)
{
return number.Value;
}
}
public struct NumberWrapper
{
public readonly Number Value;
public NumberWrapper(Number value)
{
Value = value;
}
public static implicit operator NumberWrapper(Number duration)
{
return new NumberWrapper(duration);
}
public static implicit operator Number(NumberWrapper number)
{
return number.Value;
}
}
Dieser Code kompiliert:
bool x = new Number(1) < new Number(2);
Und so natürlich wird dies:
Number n1 = new NumberWrapper(1);
Number n2 = new NumberWrapper(2);
bool z = n1 < n2;
aber dies wird nicht :
bool y = new NumberWrapper(1) < new NumberWrapper(2);
weil NumberWrapper
keine implizite Konvertierung in einen beliebigen Typ hat, der <
ohne weitere implizite Konvertierungen unterstützt.
Beachten Sie, dass alle primitiven numerischen Typen und Aufzählungstypen (z. B. char, short, int, long, float, double, decimal, enum) integrierte Vergleichsoperatoren bereitstellen. Alle anderen Typen können nur benutzerdefinierte Vergleichsoperatoren bereitstellen.
Benutzerdefinierte Vergleichsoperatoren wie folgt aussehen:
public static bool operator < (MyType lhs, MyType rhs) ...
Es relevante Informationen von Eric Lippert ist hier: http://stackoverflow.com/a/8529811/106159 –
'implicit' Umwandlungen machen es sehr einfach sich in den Fuß schießen. Sie sollten nur selten und sorgfältig verwendet werden. Und eine implizite Umwandlung in einen primitiven Typ ist nur eine schlechte Idee. –
@HenkHolterman: Ich weiß, ich versuche es vorsichtig zu verwenden :) – zgnilec