C# 2.0 让我可以访问可空类型。当我希望数据库中的 DateTime 变量为空时,这似乎非常方便。使用可空类型时我应该担心什么,或者我是否可以过分让我拥有的每个类型都可以为空?
5 回答
Mitch 的 DBNull 不为空是一个好点。还要注意这一点,这是合法的 C#,但会(幸运地)产生警告:
int x = 0;
// Much later
if (x == null)
看起来它应该是非法的,但它是有效的,因为 x 可以隐式转换为可为空的 int。永远不要忽视这个警告。
您还应该注意表面上看起来与操作员不同的东西。例如,通常你会期望:
if (x <= y || x >= y)
永远都是真的——但不是 whenx
和y
are both null
。然而,x == y
这将是真的 - 不像 SQL,而且确实不像 VB!提升的运算符行为是由语言而不是运行时提供的,因此您需要了解您使用的每种语言将做什么。
最后,确保您了解装箱如何处理可空类型。可空值类型的非空值被装箱,就好像它一开始就不可为空一样,空值被装箱到简单的空引用。(即实际上没有创建框 - 运行时只返回空值)。您可以从空引用或基础类型的框拆箱为可空值类型。那有意义吗?(我在 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.
注意DBNull
哪一个是不同的null
您还应该小心,仅在类的逻辑要求值确实可以为空的情况下才使用可空类型。这听起来可能很愚蠢,但是如果您“过火”并使所有内容都可以为空,您可能会使代码变得比必要的复杂。
当它在适当的地方使用时,我认为它可以提高代码质量,但如果它是多余的,请不要这样做。
有一个问题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
. 不寻常的装箱规则意味着 this 调用GetType()
,null
这是不可能的。GetType()
因此,如果您认为自己可能有空Nullable<T>
对象,请不要调用。
另外 - 请注意,一些数据绑定方法不太喜欢Nullable<T>
。
互操作性可能是一个问题——例如暴露给 COM 客户端或作为 Web 服务。