在C#类中使用null或Empty singleton?

时间:2018-08-18 10:43:46

标签: c# oop null

我经常偶然发现具有Empty-property的类来表示一个未知或以某种方式缺失的值。为什么不使用null呢?有一个类的Empty单例是否有充分的实际理由?考虑到在这种情况下我们可以使用可为空的属性,则可以使用这种结构。

澄清:我的意思不是我应该使用现有的Empty-like-properties还是null,而是/如果我应该为自己实现的新类添加Empty-properties。

更新:

我认为我只是将编码方面与领域建模相混淆。显然,每个域都必须将某些类似空值的值视为不可接受,例如空字符串,空数组,0,Guid.Empty等。

如果基础值类型的状态对于我的类表示的概念无效,则可以添加具有无效基础值的Empty,Undefined或类似内容来表示此状态。但是除了这种情况,我想不出添加空属性而不是仅仅使用null的原因。

3 个答案:

答案 0 :(得分:0)

  

当需要表示基础类型的未定义值时,请使用可为空的类型。 Boolean变量只能有两个值:true和false。没有“未定义”值。在许多编程应用程序中,最显着的是数据库交互,变量值可能不确定或缺失。例如,数据库中的字段可能包含true或false值,也可能根本不包含任何值。在这种情况下,您使用Nullable<bool>类型。

当您的应用程序与您具有非常有限的控制或完全没有控制权的第三方数据库/服务进行通信时,可空类型可能是最有用的。

假设您的应用程序之一处理不同的来源。您必须将源值分配给具有Reference Types (string, class, list etc.)Value Types (int, double, bool etc)属性的类之一。

您无法控制应用程序中接收到的值。尽管Reference Types将优雅地处理任何null值,但是Value Types将抛出运行时异常。这是Nullable类型将为您节省时间的地方。将值分配给您的类属性后,就可以随意使用所需的方式进行处理。

您可以在此处获取有关此主题的更多信息:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/nullable-types/

希望这会有所帮助!

答案 1 :(得分:0)

为什么有些程序员使用 Empty(或 UnknownUndefined)实例编写类而不是使用 null 的正确答案是,它是一种编程技术。

好处:它提供了一个可以访问成员的实例。您的大部分代码不再需要进行空检查,因为从不传递空值;相反,这个实例被传递。

从技术上讲:Empty 不应表示 Unknown/Undefined。例如,当您不关心变量是否已在某处显式设置时,String.Empty 是一个有用的值。无论如何,如果您想让代码正常工作,请使用它。

如果您关心检测到“从未初始化”,那么您要么将其保留为 null,要么创建一个 Unknown(或 Undefined)实例。这在实现上与 Empty 相同,只是使用方式不同。按照惯例。

名字很重要。


我个人不使用这种技术。我发现在值可能为 null 的地方执行 null 检查比检查这个特殊实例(当我需要知道它是否为 Unknown 时)更容易混淆。

或者换一种说法:我不喜欢这种技术倾向于将问题“传递给”其他代码的方式。对我来说,尽早发现错误比让编程更方便更重要。当程序员编写代码时,他们应该“知道”(定义/决定/声明)在给定点是否允许“空”。如果在不允许的地方错误地传递了“null”,我希望立即出现异常。

一些较新的语言强制执行此类知识,并且始终区分“可为空”和“不可为空”变量,即使对于类实例也是如此。这是我的偏好:预先“声明”。理想情况下,如果允许使用“null”,则要求程序员说明如何处理 null。 F# 这样做,IIRC。或者也许只是他们的“模式”(“开关/案例”的概括)需要“完整的规范”。


如果类程序员使用这种技术,他们必须确保在任何尝试改变这个特殊的 Empty 实例时都会抛出异常。

在大多数语言中,确保是一件很麻烦的事情:任何可写属性都必须包含检查是否是正在修改的 Empty 实例的逻辑。如果是,则抛出异常。

(String 类没有这个问题,因为所有的实例都是不可变的:任何创建一个改变的字符串的操作,都会将它作为一个新的字符串实例返回,保持原来的不变。) >

理想情况下,一种语言具有“真正的”“只读”功能,可以保证对象是“不可变的”。 (与 C# 和其他 C 风格的语言相比,它们允许“只读”变量的属性仍然是可写的。这在您需要时很有用;缺少的是一种声明实例完全不可变的方法,还有其他可以变异的实例。)

答案 2 :(得分:-1)

  1. e。 G。 let allQuestion = QuestionBank() override func viewDidLoad() { super.viewDidLoad() ref = Database.database().reference() GetData() } func GetData() { let ref = self.ref.child("Set1") ref.observeSingleEvent(of: .value, with: { snapshot in for child in snapshot.children { let snap = child as! DataSnapshot let set = snap.value as! Question self.list.append(set) } }) } 使操作成为可能,如果操作失败则抛出string.Empty,并抛出null

  2. 如果您在代码中的所有地方都使用NullReferenceException而不是"",则会为每种用法创建string.Empty的新实例,从而浪费内存。

注意:至少对于string而言,string属性不是Empty,而只是静态属性。