Есть ли что-то, о чем мне следует беспокоиться при использовании обнуляемых типов в .Net 2.0? - PullRequest
2 голосов
/ 02 января 2009

C # 2.0 дает мне доступ к обнуляемым типам. Это кажется очень удобным, когда я хочу, чтобы переменная DateTime в базе данных была нулевой. Есть ли что-то, о чем мне следует беспокоиться при использовании типов, допускающих обнуляемость, или я могу пойти за борт и сделать все типы, которые у меня есть, обнуляемыми?

Ответы [ 5 ]

8 голосов
/ 02 января 2009

DBNull Митча, не являющийся нулем, является хорошим пунктом. Также остерегайтесь этого, который является законным C #, но (к счастью) выдаст предупреждение:

int x = 0;

// Much later
if (x == null)

Похоже, что это должно быть недопустимо, но это допустимо, потому что x может быть неявно преобразован в обнуляемое int. Никогда не игнорируйте это предупреждение.

Вы также должны знать о том, что на поверхности кажется странным с операторами. Например, обычно вы ожидаете, что:

if (x <= y || x >= y)

будет всегда верным - но это не так, когда x и y оба null. Тем не менее, x == y будет верным - в отличие от SQL и даже в отличие от VB! Поведение отмененного оператора обеспечивается языком, а не средой выполнения, поэтому вам необходимо знать, что будет делать каждый используемый вами язык.

Наконец, убедитесь, что вы понимаете, как бокс работает с обнуляемыми типами. Непустое значение типа значения, допускающего значение NULL, помечается в штучной упаковке, как если бы оно было необнуляемым для начала, а значение NULL упаковывается в простую нулевую ссылку. (т. е. окно на самом деле не создано - среда выполнения просто возвращает ноль). Вы можете распаковать в тип значения Nullable либо из пустой ссылки, либо из поля базового типа. Имеет ли это смысл? (Я углубляюсь в это в C # in Depth, и, надеюсь, с большей ясностью ... но сейчас 8.45, а у меня не было кофе ...)

РЕДАКТИРОВАТЬ: Хорошо, может быть, пример поможет:

int? i = 5;
int? j = null;

object x = i; // x = reference to boxed int (there's no such thing as a "boxed nullable int")
object y = j; // y = null (a simple null reference)

i = (int?) x; // Unboxing from boxed int to int? is fine.
j = (int?) y; // Unboxing from a null reference to int? is fine too.
4 голосов
/ 02 января 2009

Остерегайтесь DBNull, который отличается от null

1 голос
/ 02 января 2009

Вы также должны быть осторожны, чтобы использовать только обнуляемые типы, если логика класса требует, чтобы значения действительно обнулялись. Это может прозвучать глупо, но если вы «идете за борт» и делаете все обнуляемым, вы можете сделать код более сложным, чем необходимо.

Когда это используется в соответствующих местах, я думаю, что это улучшает качество кода, но если это избыточно, не делайте этого.

0 голосов
/ 02 января 2009

Функциональная совместимость может быть проблемой - например, предоставление доступа COM-клиентам или в качестве веб-службы.

0 голосов
/ 02 января 2009

Есть ошибка с GetType(), что особенно заметно при использовании new() и обобщений для отслеживания:

static void Foo<T>() where T : new()
{
    T t = new T();
    string s = t.ToString(); // fine
    bool eq = t.Equals(t); // fine
    int hc = t.GetHashCode(); // fine
    Type type = t.GetType(); // BOOM!!!
}

По сути, GetType() необычен тем, что это не virtual, поэтому он всегда разыгрывается (в штучной упаковке) до object. Необычные правила бокса означают, что это вызывает GetType() на null, что невозможно. Поэтому не звоните GetType(), если думаете, что у вас могут быть пустые Nullable<T> объекты.

Также обратите внимание, что некоторым методам привязки данных не очень нравится Nullable<T>.

...