Почему Convert.ToString(null) возвращает другое значение, если вы выбрали нуль?

Convert.ToString(null)

возвращает

null

Как я и ожидал.

Но

Convert.ToString(null as object)

возвращает

""

Почему эти разные?

Ответ 1

Есть 2 перегрузки ToString, которые здесь вступают в игру

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

Компилятор С# по существу пытается выбрать наиболее специфическую перегрузку, которая будет работать с вводом. Значение A null конвертируется в любой ссылочный тип. В этом случае string более конкретный, чем object, и, следовательно, он будет выбран победителем.

В null as object вы укрепили тип выражения как object. Это означает, что он больше не совместим с перегрузкой string, и компилятор выбирает перегрузку object, поскольку она единственная совместимая.

По-настоящему волосатые детали того, как это работает, связаны с разделом 7.4.3 спецификации языка С#.

Ответ 2

Следующее из отличное разрешение перегрузки JaredPar ответ - остается вопрос: почему Convert.ToString(string) возвращает null, но Convert.ToString(object) return string.Empty"?

И ответ на этот вопрос... потому что документы говорят so:

Convert.ToString(string) возвращает "указанный экземпляр строки, фактическое преобразование не выполняется".

Convert.ToString(object) возвращает "строковое представление значения" или String.Empty, если значение равно null.

EDIT: Что касается этого: "ошибка в спецификации", "очень плохой дизайн API", "почему он был указан так" и т.д. - я сделаю несколько соображений, почему я не вижу его как большое дело.

  • System.Convert имеет методы преобразования каждого базового типа в себя. Это странно - поскольку преобразование не требуется или не возможно, поэтому методы в конечном итоге просто возвращают параметр. Convert.ToString(string) ведет себя одинаково. Я предполагаю, что они здесь для сценариев генерации кода.
  • Convert.ToString(object) имеет 3 варианта при передаче null. Бросьте, верните null или верните string.Empty. Бросок был бы плохим - вдвойне, поэтому с предположением они используются для сгенерированного кода. Возврат null требует, чтобы ваш вызывающий выполнял нулевую проверку - опять же, отличный выбор в сгенерированном коде. Возвращение string.Empty кажется разумным выбором. Остальная часть System.Convert имеет дело с типами значений, которые имеют значение по умолчанию.
  • Он вызывает дискуссию о том, является ли возврат null более "правильным", но string.Empty определенно более полезен. Изменение Convert.ToString(string) означает нарушение правила "без фактического преобразования". Поскольку System.Convert - статический класс утилиты, каждый метод может быть логически обработан как собственный. Там очень мало реальных сценариев, где это поведение должно быть "неожиданным", поэтому позвольте юзабилити победить (возможную) правильность.