(Der "benutzerdefinierte" im Titel bezieht sich auf die Tatsache, dass Addition und Subtraktion von TimeSpan
und DateTime
nicht Teil des C# -Standards sind definiert in der BCL.)Kuriose Überladungsauflösung bei Verwendung eines nackten Null-Literals mit benutzerdefinierten Operatoren
Herumspielen mit erhöhten Operatoren auf Nullable TimeSpan
und DateTime
Werte, schrieb ich den folgenden Code. Beachten Sie, dass das Framework verschiedene Operationen für TimeSpan
und DateTime
bietet.
Es gibt einen symmetrischen (und kommutativen) Zusatz, bei dem Sie zwei TimeSpan
aufnehmen und die Summe TimeSpan
zurückgeben. Die "Umkehrung" dieser Addition ist die Subtraktion von zwei TimeSpan
, was zu einer TimeSpan
führt.
Dann gibt es noch eine andere Art von Zusatz, asymmetrisch, wo Sie nehmen einen DateTime
(linker Operand) und einen TimeSpan
(rechten Operanden) ein DateTime
zu erzeugen. Wegen der Asymmetrie dieser Operation hat es zwei "Arten" von Umkehrungen: Eine, wo Sie zwei DateTime
voneinander subtrahieren, um die TimeSpan
Differenz zu erhalten, und eine, wo Sie eine DateTime
haben und davon subtrahieren TimeSpan
, um ein Ergebnis DateTime
zu produzieren .
static void Main()
{
DateTime? n_dt = new DateTime(2012, 12, 25);
TimeSpan? n_ts = TimeSpan.FromDays(62.0);
var a = n_dt + n_ts; // OK
var b = n_ts + n_ts; // OK
var c = null + n_dt; // OK, string concatenation! Type of expression is String
var d = null + n_ts; // OK, compiler prefers TS+TS, not DT+TS
var e = n_dt + null; // OK, DT+TS
var f = n_ts + null; // OK, TS+TS
var g = null + null; // error, type of expression is undetermined
var h = n_dt - n_dt; // OK
var i = n_dt - n_ts; // OK
var j = n_ts - n_ts; // OK
var k = null - n_dt; // OK, DT-DT
var l = null - n_ts; // compiler prefers TS-TS, not DT-TS
var m = n_dt - null; // error, compiler won't choose between DT-DT amd DT-TS, type of expression is undetermined
var n = n_ts - null; // OK, TS-TS
var o = null - null; // OK, integer subtraction! Type of expression is Nullable<Int32>
// illegal:
//var p = n_dt + n_dt;
//var q = n_ts + n_dt;
//var r = n_ts - n_dt;
}
Einige Fragen entstehen natürlich.
Es ist ein bisschen seltsam, dass o
erlaubt ist und gibt ein int?
(warum kein long?
überhaupt?), Während g
nicht zulässig ist. Ist das in der Spezifikation? Außerdem ist es ein wenig seltsam, dass das "Unmögliche" c
durch Zeichenkettenverkettung aufgelöst wird. Anscheinend entscheidet der Compiler, dass die null
in c
eine (string)null
ist. Das Hinzufügen eines Ausdrucks des expliziten Typs object
zu einem DateTime
wird dagegen nicht kompiliert.
Aber meine Hauptfrage ist: Warum kann der Compiler eine Überlastung für d
und l
wählen, aber mit m
klagt es über Zweideutigkeit?
Bei weitem das seltsamste Ding hier ist var o = null - null; –
'c' verwendet String-Verkettung, da Sprachoperatoren den benutzerdefinierten Operatoren vorgezogen werden und dieser Ausdruck dem String-Verkettungsoperator von' operator + (string, object) 'entspricht. Das wirft natürlich die Frage nach "d" auf, da durch diese Logik auch die String-Verkettung aufgelöst werden sollte. – Servy
@DaveBish Einverstanden. Ich würde annehmen, dass es zwischen int/lang ambig wäre – Servy