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

С# 4: Динамический и Nullable <>

Итак, у меня есть код, который проходит вокруг этого анонимного объекта между методами:

var promo = new
{
    Text = promo.Value,
    StartDate = (startDate == null) ?
        new Nullable<DateTime>() : 
        new Nullable<DateTime>(DateTime.Parse(startDate.Value)),
    EndDate = (endDate == null) ?
        new Nullable<DateTime>() : 
        new Nullable<DateTime>(DateTime.Parse(endDate.Value))
};

Методы, которые получают этот анонимный тип объекта, объявляют его тип как dynamic:

private static bool IsPromoActive(dynamic promo)
{
    return /* check StartDate, EndDate */
}

Однако во время выполнения, если StartDate или EndDate установлены на new Nullable<DateTime>(DateTime.Parse(...)), метод, который получает этот объект dynamic (с именем promo), выполняет следующее:

if (promo.StartDate.HasValue && promo.StartDate > DateTime.Today ||
    promo.EndDate.HasValue && promo.EndDate < DateTime.Today)
{
    return;
}

Он выдает исключение:

Server Error in '/' Application.
'System.DateTime' does not contain a definition for 'HasValue' 

Что здесь происходит? Что я не понимаю о типах Nullable и ключевом слове dynamic?

Этот код работал отлично до того, как я изменил. Я удалил struct, который ранее хранил Text, StartDate и EndDate, и заменил его анонимным типом и передал его как dynamic.

4b9b3361

Ответ 1

Отличный вопрос. Два факта, которые вы, вероятно, не знаете:

  • Динамический за кулисами - это просто объект. То есть "динамическая" переменная является "объектной" переменной с подсказкой к компилятору, который говорит "генерировать динамические операции над этой переменной при ее использовании".

  • Нет такой вещи, как с нулевым значением в коробке. Когда вы вставляете int? для объекта вы получаете либо ссылку на нулевой объект, либо вложенную строку. Обнуляемая оболочка вокруг int отбрасывается.

Теперь должно быть ясно, что здесь происходит. Если промо является динамическим, то promo.StartDate является динамическим. Это означает, что во время выполнения это объект. Это означает, что если он имеет тип значения, он помещается в коробку. Это означает, что если оно было нулевым, оно теперь является либо нулевой ссылкой, либо значением, не равным нулю. В любом случае, эта вещь не имеет свойства HasValue. Если вы хотите узнать, имеет ли тип своего значения тип nullable value, равный null, тогда проверьте, является ли promo.StartDate нулевым или нет.