为什么人们在代码中使用魔术值而不是null?

时间:2009-02-26 16:45:01

标签: magic-numbers

我在遗留代码和一些.NET开源项目中看到了这一点。 我无法想象这样做的理由。只使用“null”对我来说似乎更容易。

示例:

public class Category
{
   int parentID;

   bool HasParent
   {
      get
      {
          return parentID != -1;
      }
   }
}

public class Category
{
   int parentID;

   bool HasParent
   {
      get
      {
          return parentID != null;
      }
   }
}

6 个答案:

答案 0 :(得分:11)

因为要具有“null”值,所以类型必须是可为空的。这适用于引用类型(您定义的任何类和标准库),如果你看,你会看到人们只要有没有值的引用对象就使用null

Employee employee = Employees.Find("John Smith");
if(employee == null) throw new Exception("Employee not found");

当您使用类型(如int,char或float)时会出现此问题。与引用类型不同,引用类型指向内存中其他位置的数据块,这些值以内联方式存储和操作(没有指针/引用)。

因此,默认情况下,值类型没有空值。在您提供的代码中,parentID为不可能为空(我甚至对您的编译器感到惊讶 - Visual Studio 2008和2005可能会绘制绿色下划线并告诉您声明总是错误的。)

为了使int具有null值,您需要将其声明为可为空的

int? parentID;

现在 parentID可以包含一个空值,因为它现在是一个32位整数的指针(以及“引用”),而不仅仅是一个32位整数。

所以希望您理解为什么“魔术值”通常用于表示基本类型(值类型)的null。它只是一个很大的麻烦,通常是一个大的性能命中(查找装箱/拆箱),将这些值类型存储为值的引用,以允许它们为空。

编辑:有关装箱/拆箱的更多参考(您需要有一个int == null),请参阅MSDN上的文章:

  

装箱和拆箱(C#编程指南)

     

性能

     

关于简单分配,装箱和拆箱是计算上昂贵的过程。装箱值类型时,必须分配和构造新对象。在较小程度上,拆箱所需的演员阵容在计算上也是昂贵的。有关更多信息,请参阅性能。

答案 1 :(得分:4)

这些通常是在用C语言编程时产生的习惯。许多C程序员会因浪费可空的int而烦恼,这至少需要一个额外的位,甚至可能需要一个指针。当你知道值为正且你有足够的负值空间用于标志时,这尤其糟糕。 -1可以表示未设置,-2表示parentId在此节点的上下文中甚至没有意义,-3表示该节点具有无法处理工作的父节点并且留在饮酒狂欢中从来没有见过,等...

在C#世界中,可以为空的int(以及它们与RDMS的简单集成)以及具有2GB + RAM的计算机的清晰度意味着旧的C习惯正在慢慢消亡,但旧的习惯会变得很难。

答案 2 :(得分:3)

拥有null对象可能导致抛出异常,而错误代码(如“-1”失败情况)不会抛出异常。

这对于不能很好地处理异常的语言或应用程序来说至关重要。

答案 3 :(得分:2)

在大数据仓库上工作时,如果为null,我有时会使用0值来在我的多维数据集中插入非空值。 我总是有一个0 id对应所有维度的'未知'值,所以我有一个没有空值的立方体。

主要的兴趣是提供更简单,更有效的查询

答案 4 :(得分:1)

可以在每种语言/环境中使用可空值类型;它们被添加到.Net 2.0中。如果您的遗留代码是基于.Net并且是使用1.1框架启动的,那么您的答案是null当时不是一个选项。

答案 5 :(得分:0)

你真的看过要看的应用吗?只要幻数保存在一个带有描述性名称的地方,它就会非常有用。