Есть ли "?." оператор делает что-нибудь еще, кроме проверки на ноль?
Как вы, возможно, знаете, 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");