代码之家  ›  专栏  ›  技术社区  ›  Matthew Vines

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

  •  35
  • Matthew Vines  · 技术社区  · 15 年前

    为什么我要在c#中使用不可为空的数据类型?(一个更好的问题是,为什么我不在默认情况下选择可为null的类型,而只在显式有意义时使用不可为null的类型。)

    选择可为空的数据类型而不是其不可为空的对等数据类型是否会对性能造成“重大”影响?

    我更喜欢根据null检查值,而不是Guid.empty、string.empty、DateTime.MinValue、<=0等,并且通常使用可为空的类型。我不经常选择可空类型的唯一原因是我后脑勺发痒的感觉,这让我觉得不仅仅是向后兼容迫使额外的“?”字符显式允许空值。

    是否有人总是(最总是)选择可空类型而不是不可空类型?

    7 回复  |  直到 14 年前
        1
  •  50
  •   Stack Overflow is garbage    15 年前

    您不应该总是使用可空类型的原因是,有时您可以保证 被初始化。你应该尽可能多地设计你的代码。如果没有未初始化的合法值,那么可能没有未初始化的值。作为一个非常简单的例子,考虑一下:

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

    总是 有效的这是不可能的 c 可能未初始化。如果它变成了一个 int? ,您将有效地告诉代码读者“此值可能为null。请确保在使用它之前进行检查”。但是我们知道这永远不会发生,所以为什么不在代码中公开这个保证呢?

    在值是可选的情况下,您是绝对正确的。如果我们有一个函数可能返回字符串,也可能不返回字符串,那么返回null。不要返回string.Empty()。不要返回“魔法值”。

    但并非所有值都是可选的。使所有内容都可选会使代码的其余部分变得更加复杂(它会添加另一个必须处理的代码路径)。

    如果您可以明确保证此值始终有效,那么为什么要丢弃此信息?这就是通过将其设置为可空类型来实现的。现在,该值可能存在,也可能不存在,任何使用该值的人都必须处理这两种情况。但你知道,首先,这些情况中只有一个是可能的。因此,请帮助代码的用户,并在代码中反映这一事实。然后,代码的任何用户都可以依赖有效的值,他们只需要处理一种情况,而不是两种情况。

        2
  •  9
  •   LukeH    15 年前

    因为总是要检查可空类型是否为 null .

    // 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();
    
        3
  •  3
  •   Brian    15 年前

    我认为语言设计者认为“引用类型在默认情况下可以为null”是一个错误,而非null是唯一合理的默认值,您应该选择为null。(许多现代函数式语言都是这样。)“null”通常是一堆麻烦。

        4
  •  3
  •   John Rasch    15 年前

    你似乎有两个不同的问题。。。

    为什么我要在C#中使用不可为空的数据类型?

    为什么默认情况下我不选择可为null的类型,而只在显式有意义时使用不可为null的类型?

    正如Joel已经提到的,只有当类型是引用类型时,它才能为null。编译器保证值类型具有值。如果您的程序依赖于一个变量来获得一个值,那么这就是您希望通过不选择可为null的类型来实现的行为。

    当然,当您的数据来自非您的程序的任何地方时,所有的赌注都是无效的。最好的例子是数据库。数据库字段可以是 null 无效的 . 可以使用可为空的类型执行此操作。

        5
  •  1
  •   Community kfsone    7 年前

    尽管空值可以方便地用作“尚未初始化”或“未指定”值,但它们使代码更加复杂,主要是因为您重载了 null 以及变量(数字或空值vs.just-a-number)。

    空值受到许多数据库设计师和SQL数据库程序员的青睐,但只要稍微改变一下对这个问题的思考,您就可以消除空值,并且实际上拥有更简单、更可靠的代码(例如,不必担心 NullReferenceException

    另见问题, Why is “null” present in C# and java?

        6
  •  0
  •   Jonathan Rupp    15 年前

    我倾向于在任何有意义的地方使用可空类型——在出现问题之前,我不会关心性能,然后我将修复它所在的几个方面并完成它。

    然而,我还发现,一般来说,我的大多数值最终都是不可为空的。事实上,有很多次我真的想要一个NotNullable,当我得到null时,我可以使用它来查找null问题,而不是稍后尝试使用它时。

        7
  •  -2
  •   Flagrum    10 年前

    唯一应该使用可空类型的时间是在数据库表中的某个字段绝对要求应用程序在某个点发送或接收空类型的情况下。即使在这种情况下,也应该始终尝试找到一种方法来避免使用可为null的类型。布尔并不总是你最好的朋友。