C # 4: динамический и обнуляемый <> - PullRequest
33 голосов
/ 16 сентября 2010

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

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.

1 Ответ

63 голосов
/ 16 сентября 2010

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...