(Określenie "zdefiniowane przez użytkownika" w tytule odnosi się do faktu, że dodawanie i odejmowanie TimeSpan
i DateTime
nie jest częścią standardu C#. zdefiniowany w BCL.)Ciekawa rozdzielczość przeciążania, gdy używany jest pusty znak null z operatorami zdefiniowanymi przez użytkownika
Zabawy z podniesionymi operatorami na wartości zerowe TimeSpan
i DateTime
wartości, napisałem następujący kod. Zauważ, że framework oferuje różne operacje na TimeSpan
i DateTime
.
Istnieje jeden symetryczny (i komutatywny) dodatek, w którym przyjmujemy dwa TimeSpan
i zwracamy sumę TimeSpan
. "Odwrotność" tego dodawania jest odjęciem dwóch TimeSpan
uzyskując TimeSpan
.
Potem jest inny rodzaj Ponadto, asymetryczny, gdzie można podjąć jedną DateTime
(lewy operand) i jeden TimeSpan
(prawy operand) w celu wytworzenia DateTime
. Ze względu na asymetrię tej operacji, ma dwa „rodzaje” o odwrotności: Jedna gdzie odjąć dwa DateTime
od siebie, aby uzyskać różnicę TimeSpan
i jedną gdzie trzeba DateTime
i odjąć od niej jeden TimeSpan
pozwoliło uzyskać DateTime
.
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;
}
Niektóre pytania pojawiają się naturalnie.
To trochę dziwne, że o
wolno i daje int?
(dlaczego nie long?
w drodze?) Podczas g
jest niedozwolone. Czy to w specyfikacji? Ponadto, jest trochę dziwne, że "niemożliwe" c
jest rozwiązywany przez konkatenację ciągów. Wygląda na to, że kompilator zdecydował, że null
w c
jest (string)null
. Z drugiej strony dodanie wyrażenia typu jawnego: object
do DateTime
nie zostanie skompilowane.
Ale moje główne pytanie brzmi: Dlaczego kompilator wybrać przeciążenie dla d
i l
, ale m
to narzeka dwuznaczności?
Do tej pory najdziwniejszą rzeczą tutaj jest var o = null - null; –
'c' używa konkatenacji ciągów znaków, ponieważ operatory języków są preferowane w stosunku do operatorów zdefiniowanych przez użytkownika, a wyrażenie to pasuje do operatora konkatenacji łańcuchów operatora' operator + (ciąg, obiekt) '. To oczywiście podnosi kwestię 'd' chociaż, jak przez tę logikę, która powinna również rozwiązać ciąg konkatenacji. – Servy
@DaveBish Zgoda. Zakładam, że byłoby to nieuchwytne między int/long – Servy