简体   繁体   English

为什么我不总是在C#中使用可为空的类型

[英]Why shouldn't I always use nullable types in C#

I've been searching for some good guidance on this since the concept was introduced in .net 2.0. 自从.net 2.0中引入此概念以来,我一直在寻找有关此问题的良好指导。

Why would I ever want to use non-nullable data types in c#? 为什么我要在c#中使用不可为空的数据类型? (A better question is why wouldn't I choose nullable types by default, and only use non-nullable types when that explicitly makes sense.) (一个更好的问题是,为什么我默认情况下不选择可空类型,而只在明确有意义的情况下才使用非空类型。)

Is there a 'significant' performance hit to choosing a nullable data type over its non-nullable peer? 选择非空对等数据类型的可空数据类型是否会对性能产生重大影响?

I much prefer to check my values against null instead of Guid.empty, string.empty, DateTime.MinValue,<= 0, etc, and to work with nullable types in general. 我更喜欢针对null而不是Guid.empty,string.empty,DateTime.MinValue,<= 0等检查我的值,并且通常使用可为null的类型。 And the only reason I don't choose nullable types more often is the itchy feeling in the back of my head that makes me feel like it's more than backwards compatibility that forces that extra '?' 我不经常选择可为空的类型的唯一原因是我的后脑发痒,这让我感觉不仅仅是向后兼容会导致额外的“?” character to explicitly allow a null value. 字符,以明确允许空值。

Is there anybody out there that always (most always) chooses nullable types rather than non-nullable types? 有没有人总是(最经常)选择可空类型而不是非可空类型?

Thanks for your time, 谢谢你的时间,

The reason why you shouldn't always use nullable types is that sometimes you're able to guarantee that a value will be initialized. 之所以不总是使用可为空的类型,是因为有时您可以保证初始化一个值。 And you should try to design your code so that this is the case as often as possible. 而且,您应该尝试设计代码,以便尽可能多地出现这种情况。 If there is no way a value can possibly be uninitialized, then there is no reason why null should be a legal value for it. 如果无法对值进行初始化,则没有理由为什么null应该是合法值。 As a very simple example, consider this: 作为一个非常简单的示例,请考虑以下问题:

List<int> list = new List<int>()
int c = list.Count;

This is always valid. 始终是有效的。 There is no possible way in which c could be uninitialized. 没有任何可能的方法可以初始化c If it was turned into an int? 如果它变成一个int? , you would effectively be telling readers of the code "this value might be null. Make sure to check before you use it". ,您实际上会告诉代码的读者“此值可能为null。使用前请务必进行检查”。 But we know that this can never happen, so why not expose this guarantee in the code? 但是我们知道这永远不会发生,那么为什么不在代码中公开这种保证呢?

You are absolutely right in cases where a value is optional. 如果值是可选的,那么您绝对正确。 If we have a function that may or may not return a string, then return null. 如果我们有一个可能会或可能不会返回字符串的函数,则返回null。 Don't return string.Empty(). 不要返回string.Empty()。 Don't return "magic values". 不要返回“魔术值”。

But not all values are optional. 但并非所有值都是可选的。 And making everything optional makes the rest of your code far more complicated (it adds another code path that has to be handled). 并且使所有内容都可选,使其余代码变得更加复杂(它增加了另一个必须处理的代码路径)。

If you can specifically guarantee that this value will always be valid, then why throw away this information? 如果可以明确保证此值始终有效,那么为什么要丢弃此信息呢? That's what you do by making it a nullable type. 这就是使它成为可为空的类型的方法。 Now the value may or may not exist, and anyone using the value will have to handle both cases. 现在,该值可能存在或不存在,并且使用该值的任何人都必须处理这两种情况。 But you know that only one of these cases is possible in the first place. 但是您知道,首先这些情况只有一种可能。 So do users of your code a favor, and reflect this fact in your code. 您的代码用户也是如此,并在您的代码中反映这一事实。 Any users of your code can then rely on the value being valid, and they only have to handle a single case rather than two. 然后,您的代码的任何用户都可以依靠该值是否有效,而他们只需要处理一个个案而不是两个个案。

Because it's inconvenient to always have to check whether the nullable type is null . 因为总是必须检查可空类型是否为null这很不方便。

Obviously there are situations where a value is genuinely optional, and in those cases it makes sense to use a nullable type rather than magic numbers etc, but where possible I would try to avoid them. 显然,在某些情况下,值是真正可选的,在这种情况下,使用可为空的类型而不是幻数是有意义的,但是在可能的情况下,我会尽量避免使用它们。

// 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();

I think the language designers feel that 'reference types being nullable by default' was a mistake, and that non-nullable is the only sensible default, and you should have to opt into nullness. 我认为语言设计人员认为“引用类型默认情况下可为空”是一个错误,并且非空值是唯一明智的默认值,因此您应该选择使用空值。 (This is how it is in many modern functional languages.) "null" is usually a heap of trouble. (这在许多现代功能语言中都是这样。)“空”通常是一堆麻烦。

You seem to have 2 different questions... 您似乎有2个不同的问题...

Why would I ever want to use non-nullable data types in C#? 为什么我要在C#中使用不可为空的数据类型?

Simple, because the value-type data you're relying on is guaranteed by the compiler to actually have a value! 很简单,因为编译器保证您所依赖的值类型数据实际上具有值!

Why wouldn't I choose nullable types by default, and only use non-nullable types when that explicitly makes sense? 为什么我默认不选择可为空的类型,而仅在明确有意义的情况下才使用非可为空的类型?

As Joel has already mentioned, a type can only be null if it is a reference type. 正如Joel已经提到的那样,如果类型是引用类型,则只能为null。 Value types are guaranteed by the compiler to have a value. 编译器保证值类型具有值。 If your program depends on a variable to have a value, then this is the behavior you will want by not choosing a nullable type. 如果您的程序依赖于变量具有值,则这是您不选择可为空的类型所希望的行为。

Of course, when your data is coming from anywhere that is not your program, then all bets are off. 当然,当您的数据来自不是程序的任何地方时,所有的赌注都关闭了。 The best example is from a database. 最好的例子是来自数据库。 Database fields can be null , so you would want your program variable to mimic this value - not just create a "magic" value (ie -1, 0, or whatever) that "represents" null . 数据库字段可以为null ,因此您希望您的程序变量模仿该值-不仅仅是创建“代表” null的“魔术”值(即-1、0或其他null You do this with nullable types. 您可以使用可为空的类型。

Although null values can be convenient for using as "not-initialized-yet" or "not-specified" values, they make the code more complex, mainly because you're overloading the meaning of null as well as the variable (number-or-null vs. just-a-number). 尽管null值可以方便地用作“ not-initialized-yet”或“ not-specified”值,但它们会使代码更加复杂,这主要是因为您正在重载null的含义以及变量(数字或-null与。

NULL values are favoured by many database designers and SQL database programmers but with a small change in thinking about the problem you can do away with null values and actually have simpler and more reliable code (eg, no worrying about NullReferenceException s). NULL值受到许多数据库设计人员和SQL数据库程序员的青睐,但是在思考问题上所做的更改很小,您可以消除null值,而实际上拥有更简单,更可靠的代码(例如,不必担心NullReferenceException )。

There's actually a large demand for a "T!" 实际上,对“ T”的需求很大。 operator that makes any reference type non-nullable, similar to how "T?" 使得任何引用类型都不能为空的运算符,类似于“ T?” makes value types nullable, and Anders Hejlsberg, the inventor of C#, wished he had included the ability. 使值类型可为空,C#的发明者Anders Hejlsberg希望他包括该功能。

See also the question, Why is “null” present in C# and java? 另请参阅问题, 为什么C#和Java中存在“空”?

I tend to use Nullable types wherever they make sense -- I won't care about performance until it's a problem, then I'll fix the few areas where it is and be done with it. 我倾向于在任何有意义的地方使用Nullable类型-在出现问题之前我不会在意性能,然后我将修复其中的少数问题并加以解决。

However, I also find that in general, most of my values end up being non-nullable. 但是,我还发现,总的来说,我的大多数价值观最终都是不可为空的。 In fact, there are many times I'd actually like a NotNullable I can use with reference types to find out about a null problem when I get the null, not later on when I try to use it. 实际上,实际上我有很多次想要一个NotNullable,我可以将其与引用类型一起使用,以便在我得到null时发现有关null的问题,而不是稍后再尝试使用它时。

The only time that a Nullable Type should ever be used, is in the case that a certain field in a table of the database absolutely requires that a null be sent or received by the application at some point. 只有在数据库表中的某个字段绝对要求应用程序在某个时候发送或接收null的情况下,才应使用Nullable Type。 Even in such a case, one should always try to find a way around using the Nullable Type. 即使在这种情况下,也应该始终设法找到一种使用Nullable Type的方法。 Bool isn't always your best friend. 布尔并不总是您最好的朋友。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM