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

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

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

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

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

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

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

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

3 ответа

Решение

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

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

DateTime? это только приятный синтаксис для Nullable<DateTime> который не содержит DateTime свойства и метод, в то время как оператор Элвиса работает над ненулевым 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> s с оператором Элвиса, делая его возвращаемое значение необнуляемым T сам.

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

Принимая во внимание:

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 ведьма IFormatable и есть ToString(string format) метод.

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

DateTime? dt = DateTime.Now;
string x;
if(dt.HasValue)
    x = dt.Value.ToString("dd/MM/yyyy");
Другие вопросы по тегам