2016-01-29 47 views
29

Jak pewnie wiesz, DateTime? nie posiada sparametryzowanego ToString (dla celów formatowania danych wyjściowych), a robi coś podobnegoCzy "?." operator robi cokolwiek innego oprócz sprawdzania zerowej wartości?

DateTime? dt = DateTime.Now; 
string x; 
if(dt != null) 
    x = dt.ToString("dd/MM/yyyy"); 

rzuci

nr przeciążenie dla metody „ToString” trwa 1 argumenty

Ale ponieważ C# 6.0 i Elvis (?.) operator, powyższy kod może być zastąpiony

x = dt?.ToString("dd/MM/yyyy"); 

która .... działa! Czemu?

+1

Po przeczytaniu odpowiedzi, nie mogę pomóc, ale czuję, że prawdziwe rozwiązanie problemu idzie tak: „Wystarczy użyć' dt.Value.ToString() 'już" –

+0

Co zrobić, jeśli dt ma wartość zerową? –

+0

Ya, po prostu wywołanie dt.Value.ToString() będzie wybuchać, jeśli dt ma wartość null; zdecydowanie chcesz korzystać z Operatora Elvisa, nie tylko dlatego, że ma on niesamowite imię, ale dlatego, że obsługuje dla ciebie czek NULL. dt? .Value.ToString() zasadniczo mówi: "Jeśli dt nie ma wartości NULL, wówczas uzyskaj dostęp do jego właściwości Value i przekonwertuj ją na łańcuch znaków, jeśli jest NULL, zignoruj ​​połączenie i nie rób nic" –

Odpowiedz

20

Ponieważ Nullable<T> jest zaimplementowany w języku C# w taki sposób, że instancje tej struktury pojawiają się jako typy zerowujące. Gdy masz DateTime? to faktycznie Nullable<DateTime>, po przypisaniu null temu masz ustawienie HasValue do false za kulisami, kiedy sprawdzić null, jesteś sprawdzanie HasValue itp Operator ?. jest właśnie realizowany w sposób zastępuje te same idiomy, które działają dla typów referencyjnych także dla struktur null. Podobnie jak reszta języka sprawia, że ​​struktury zerowalne są podobne do typów referencyjnych (w odniesieniu do null -ness).

14

Krótka odpowiedź:

DateTime? jest tylko słodki składnia Nullable<DateTime> który nie zawiera DateTime „s właściwości i metody podczas operator Elvis działa na nie-Nullable Nullable<DateTime>.Value.


Objaśnienie:

Następujący kod:

DateTime? dt = DateTime.Now; 
string x; 
if (dt != null) 
    x = dt?.ToString("dd/MM/yyyy"); 

Gdy decompiles jak C# 5.0 daje następujący wynik:

DateTime? nullable = new DateTime?(DateTime.Now); 
if (nullable.HasValue) 
{ 
    string str = nullable.HasValue ? nullable.GetValueOrDefault().ToString("dd/MM/yyyy") : null; 
} 

Side uwaga: string wydaje zadeklarowane wewnątrz if ma znaczenia z powodu podnoszenia na poziomie MSIL, a ponieważ wartość nie jest używany później na Dekompilator pokazuje go tak, jakby był to deklarowane wewnątrz tej if zakresie.

Jak widać, a od DateTime? jest tylko słodki składnia Nullable<DateTime>, C# ma konkretnego odniesienia do Nullable<T> s z operatorem Elvis, dzięki czemu jego wartość zwracana T non-zerowalne sam .

Wynikiem całego Elvis operator musi być Nullable więc, jeśli chcesz otrzymywać niebędącą string wartość musiałaby być Nullable<T> lub ReferenceType ale to nie zmienia faktu, że jeśli operator zdołał uzyskać wartość Nullable<DateTime> - zwrócony DateTime już nie jest Nullable<DateTime>.

+4

Down Wyborca ​​proszę wyjaśnić, więc mogę poprawić moją odpowiedź. –

+0

powinieneś usunąć "if" wokół przypisania łańcucha. Neguje operatora trójskładnikowego wewnątrz. –

+0

Nie, ponieważ 'string' nie jest później używany, jest to optymalizacja kompilatora. Jest to rzeczywisty kod dekompilowany w odbłyśniku ... –

2

Biorąc pod uwagę:

DateTime? dt = DateTime.Now; 
string x; 
if(dt != null) 
    x = dt.ToString("dd/MM/yyyy"); 

Tutaj dt jest DateTime? lub Nullable<DateTime> czarownica nie jest IFormatable i nie ma sposobu ToString(string format).

Rzuca.

Teraz rozważa:

x = dt?.ToString("dd/MM/yyyy"); 

?. to cukier syntaktyczny dla:

dt.HasValue ? dt.Value.ToString("dd/MM/yyyy"): null 

Tutaj dt.Value jest DateTime czarownica jest IFormatable i mieć metodę ToString(string format).

końcu dobry sposób, aby napisać pierwszy kod w C# 5.0 jest:

DateTime? dt = DateTime.Now; 
string x; 
if(dt.HasValue) 
    x = dt.Value.ToString("dd/MM/yyyy");