Подтвердить что ты не робот

Есть ли "?". оператор делает что-нибудь еще, кроме проверки на нуль?

Как вы знаете, DateTime? не имеет параметризованного ToString (для форматирования вывода) и делает что-то вроде

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

будет бросать

Нет перегрузки для метода 'ToString' принимает 1 аргумент

Но, поскольку С# 6.0 и оператор Elvis (?.), вышеуказанный код можно заменить на

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

который... работает! Почему?

4b9b3361

Ответ 1

Поскольку Nullable<T> реализуется на С# таким образом, что экземпляры этой структуры отображаются как типы с нулевым значением. Если у вас есть DateTime? на самом деле Nullable<DateTime>, когда вы назначаете null этому, вы устанавливаете HasValue на false за кулисами, когда вы проверяете null, вы проверяете на HasValue и т.д. Оператор ?. просто реализуется таким образом, что он заменяет те же самые идиомы, которые работают для ссылочных типов также для нулевых структур. Точно так же, как и весь остальной язык, он делает структуры с нулевыми значениями похожими на ссылочные типы (в отношении null -ness).

Ответ 2

Короткий ответ:

DateTime? - это только сладкий синтаксис Nullable<DateTime>, который не содержит свойств и методов DateTime, а Оператор Элвиса работает с не-Nullable Nullable<DateTime>.Value.


Объяснение:

Следующий код:

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

При декомпиляции как C# 5.0 получается следующий результат:

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

Боковое примечание: string кажется объявленным внутри if не имеет значения из-за подъема на уровне MSIL, и поскольку значение не используется позже, декомпилятор показывает это, как если бы он был объявлен внутри области if.

Как вы видите, и поскольку DateTime? является только сладким синтаксисом для Nullable<DateTime>, C# имеет конкретную ссылку для Nullable<T> с оператором Элвиса, что делает его возвращаемое значение непустым значением T сам.

Результат целого Elvis operator должен быть Nullable, поэтому, если вы хотите получить значение не string, оно должно быть либо Nullable<T>, либо ReferenceType > но это не меняет того факта, что если оператору удалось получить значение Nullable<DateTime> - возвращенный DateTime больше не Nullable<DateTime>.

Ответ 3

Учитывая:

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

Здесь dt есть DateTime? или Nullable<DateTime> ведьма не IFormatable и не имеет метода ToString(string format).

Так что он бросает.

Теперь рассмотрим:

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

?. является синтаксическим сахаром для:

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

Здесь dt.Value есть DateTime witch is IFormatable и имеет метод ToString(string format).

Наконец, хороший способ написать первый код в С# 5.0:

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