Dlaczego Convert.ToString (null) zwraca inną wartość, jeśli rzucisz null?


116
Convert.ToString(null)

zwroty

null

Jak oczekiwałem.

Ale

Convert.ToString(null as object)

zwroty

""

Dlaczego są różne?

Odpowiedzi:


143

W ToStringgrę wchodzą tutaj 2 przeciążenia

Convert.ToString(object o);
Convert.ToString(string s);

Kompilator C # zasadniczo próbuje wybrać najbardziej szczegółowe przeciążenie, które będzie działać z danymi wejściowymi. nullWartość jest zamienny do każdego rodzaju odniesienia. W tym przypadku stringjest bardziej szczegółowy niż objecti dlatego zostanie wybrany jako zwycięzca.

W null as objectjuż zestalony rodzaj ekspresji jako object. Oznacza to, że nie jest już zgodny z stringprzeciążeniem, a kompilator wybiera objectprzeciążenie, ponieważ jest jedynym pozostałym zgodnym.

Naprawdę skomplikowane szczegóły tego, jak działa to łamanie powiązań, są omówione w sekcji 7.4.3 specyfikacji języka C #.


15
Dobrze. Więc używa jednego przeciążenia zamiast drugiego. Ma sens. Ale czy oba przeciążenia nie powinny zwracać tego samego? +1 btw.
John MacIntyre,

2
@JohnMacIntyre - To zależy od zespołu programistów, a nie od kompilatora.
JonH,

8
@JohnMacIntyre Jeśli spojrzysz na implementację, Convert.ToString(string)jest to tylko funkcja tożsamości, podczas gdy w Convert.ToString(object)rzeczywistości przechodzi trudniejszą ścieżkę. Na pierwszy rzut oka zgodziłbym się, że powinny zwrócić to samo, ale warstwa konwertowalna BCL nie jest czymś, w czym jestem bardzo kompetentny i możliwe, że istnieje dobry powód do tej różnicy (chociaż jestem sceptyczny)
JaredPar

Przyszedłem tutaj, szukając sposobu przekonwertowania obiektu zerowego na ciąg pusty. Odpowiedzią dla innych poszukiwaczy jest (string)null, lub jeśli sprzeciwiasz się nazwie o, to(string)o
rayzinnz

65

Kontynuując doskonałą odpowiedź JaredPar dotyczącą rozwiązania problemu z przeciążeniem - pozostaje pytanie „dlaczego Convert.ToString(string)zwraca wartość null, ale Convert.ToString(object)zwraca string.Empty”?

Odpowiedź na to brzmi ... ponieważ tak mówią doktorzy :

Convert.ToString (string) zwraca „określoną instancję ciągu; żadna rzeczywista konwersja nie jest wykonywana”.

Convert.ToString (object) zwraca „ciąg znaków reprezentujący wartość lub String.Empty, jeśli wartość ma wartość null”.

EDYCJA: Jeśli chodzi o to, czy jest to „błąd w specyfikacji”, „bardzo zły projekt interfejsu API”, „dlaczego zostało to określone w ten sposób” itp. - spróbuję wyjaśnić, dlaczego nie widzę to wielka sprawa.

  1. System.Convertposiada metody konwersji każdego typu podstawowego na siebie . Jest to dziwne - ponieważ żadna konwersja nie jest potrzebna ani możliwa, więc metody w końcu zwracają tylko parametr. Convert.ToString(string)zachowuje się tak samo. Przypuszczam, że są one tutaj dla scenariuszy generowania kodu.
  2. Convert.ToString(object)po zaliczeniu ma 3 możliwości null. Throw, return null lub return string.Empty. Rzucanie byłoby złe - podwójnie więc przy założeniu, że są one używane do generowanego kodu. Zwracanie wartości null wymaga, aby dzwoniący sprawdził wartość null - znowu nie jest to świetny wybór w wygenerowanym kodzie. Zwracanie string.Empty wydaje się rozsądnym wyborem. Reszta umów System.Convertdotyczy typów wartości - które mają wartość domyślną.
  3. Jest dyskusyjne, czy zwrócenie null jest bardziej "poprawne", ale string.Empty jest zdecydowanie bardziej użyteczne. Zmiana Convert.ToString(string)oznacza złamanie zasady „brak faktycznej konwersji”. Ponieważ System.Convertjest to statyczna klasa narzędziowa, każda metoda może być logicznie traktowana jako własna. Niewiele jest rzeczywistych scenariuszy, w których takie zachowanie powinno być „zaskakujące”, więc pozwólmy użyteczności wygrać z (możliwą) poprawnością.

Czy można powiedzieć, że to błąd w specyfikacji?
John MacIntyre

3
to nie wyjaśnia, dlaczego tak jest. Stwierdzenie, że zachowuje się w ten sposób, ponieważ zostało udokumentowane, że zachowuje się w ten sposób, jest tautologiczne.
CodesInChaos

2
@JohnMacIntyre IMO można śmiało powiedzieć, że jest to bardzo zły projekt API.
CodesInChaos

7
@CodeInChaos - nie jest to tautologia, chyba że założysz, że dokumenty zostały napisane w oparciu o obserwowalne zachowanie po opracowaniu BCL. Myślę, że byłoby to dziwne założenie. IOW, nie jest „udokumentowane, że zachowuje się w ten sposób”, jest „udokumentowane, że będzie się tak zachowywać” - tj. „ Określono, aby zachowywać się w ten sposób”.
Mark Brackett

8
To tylko przesuwa pytanie do „dlaczego określono, że ma się tak zachowywać”
CodesInChaos
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.