为什么我不应该总是在C#中使用可为空的types
自从.net 2.0引入这个概念以来,我一直在寻找一些很好的指导。
为什么我会想在c#中使用不可空数据types? (一个更好的问题是,为什么我不会默认select可空types,只有在明确有意义时才使用非空types。)
在非空对等体上select可空数据types是否存在“重大”性能影响?
我更喜欢检查我的值对null而不是Guid.empty,string.empty,DateTime.MinValue,<= 0等,并与一般可空types的工作。 而且我不经常select可空types的唯一原因就是我脑海中的痒感,这让我觉得这不仅仅是向后兼容,而是强制这些额外的“? 字符显式允许空值。
有没有人总是(总是)select可空types而不是非空types?
谢谢你的时间,
你不应该总是使用可空types的原因是有时你可以保证一个值将被初始化。 而且你应该尽量devise你的代码,以便尽可能多的情况下。 如果没有办法一个值可能是未初始化的,那么为什么null应该是一个合法的值没有理由。 作为一个非常简单的例子,考虑一下:
List<int> list = new List<int>() int c = list.Count;
这总是有效的。 有没有可能的方式,其中c
可能是未初始化的。 如果它变成了一个int?
,你会有效地告诉读者代码“这个值可能是空的,在使用之前一定要检查”。 但是我们知道这是不可能发生的,所以为什么不在代码中公开这个保证呢?
如果值是可选的,您绝对正确。 如果我们有一个可能返回或不可以返回string的函数,则返回null。 不要返回string.Empty()。 不要返回“魔法值”。
但并不是所有的值都是可选的。 使所有东西都可选,使得其余的代码更加复杂(它增加了另一个必须处理的代码path)。
如果你能特别保证这个值永远是有效的,那么为什么要扔掉这些信息呢? 这就是你做一个可以为空的types。 现在值可能存在也可能不存在,任何使用该值的人都必须处理这两种情况。 但是你知道只有其中一种情况是可能的。 因此,您的代码的用户有利,并在您的代码中反映这一事实。 你的代码的任何用户都可以依赖这个有效的值,他们只需要处理一个事件而不是两个事件。
因为总是需要检查可为空的types是否为空,这是不方便的。
很显然,在某些情况下,值是真正可选的,在这种情况下,使用可以为空的types而不是幻数等是合理的,但在可能的情况下,我会尽量避免。
// nice and simple, this will always work int a = myInt; // compiler won't let you do this int b = myNullableInt; // compiler allows these, but causes runtime error if myNullableInt is null int c = (int)myNullableInt; int d = myNullableInt.Value; // instead you need to do something like these, cumbersome and less readable int e = myNullableInt ?? defaultValue; int f = myNullableInt.HasValue ? myNullableInt : GetValueFromSomewhere();
你好像有两个不同的问题
为什么我会想要在C#中使用不可空数据types?
很简单,因为您所依赖的值types数据是由编译器保证实际上有一个值!
为什么我不会默认select可为空的types,并且只有在明确有意义时才使用不可空的types?
正如Joel已经提到的那样,如果一个types是一个引用types,它只能是null。 值types由编译器保证有一个值。 如果你的程序依赖于一个variables有一个值,那么这是你不想select一个可为空的types的行为。
当然,当你的数据来自任何不是你的程序的地方,那么所有的赌注都是closures的。 最好的例子是从数据库。 数据库字段可以是null
,所以你会希望你的程序variables模仿这个值 – 不只是创build一个“魔术”值(即-1,0,或其他)“表示” null
。 你可以使用可为空的types。
我认为语言devise者认为“缺省的可以为空的引用types”是一个错误,不可空的是唯一明智的缺省,你应该select无效。 (这在许多现代函数式语言中是如此)。“null”通常是一堆麻烦。
我倾向于在任何有意义的地方使用Nullabletypes – 在问题出现之前我不会在乎性能,然后我将修复它的一些地方并完成它。
不过,我也发现一般来说,我的大部分值最终都是不可空的。 事实上,有很多次我真的喜欢一个NotNullable我可以使用引用types来找出null的问题,当我得到null,而不是在以后的时候,当我尝试使用它。
尽pipe空值可以方便地用作“未初始化的”或“未指定的”值,但是它们使得代码更加复杂,主要是因为你重载了null
的含义以及variables(number-or – 与只是一个数字)。
NULL值被许多数据库devise者和SQL数据库程序员所青睐,但是考虑到这个问题,你可以用空值去掉一些小的变化,并且实际上有更简单和更可靠的代码(例如,不用担心NullReferenceException
)。
实际上对“T!”有很大的需求 运算符,使任何引用types不可为空,类似于“T?” 使价值types可以为空,而C#的发明者Anders Hejlsberg希望他包含了这个能力。
另请参阅问题, 为什么C#和Java中存在“null”?
唯一可以使用Nullable Type的时候,就是数据库表中某个字段绝对要求应用程序在某个时刻发送或接收null。 即使在这种情况下,也应该总是试图find一种使用可空types的方法。 布尔并不总是你最好的朋友。