将引用类型声明为const有用吗

本文关键字:有用 const 引用类型 声明 | 更新日期: 2024-09-19 09:41:58

为什么有人会这样做:

const object useless = null;
const IEnumerable meaningless = null;

Eric Lippert说,默认情况下,功能是不实现的,每种可能性都会增加测试、维护等方面的工作量。为什么引用类型的null值需要作为常量?

将引用类型声明为const有用吗

Servy的观点很好。让我用一种稍微不同的方式来解释这一点。

让我们先问一个更普遍的问题"C#1.0编译器应该将引用类型的null文本归类为常量吗?"我想强调的是,我们在这里是在推理C#1.0,所以你不会考虑任何关于null值类型或泛型的问题。

那么,把任何东西归为常数有什么意义呢?关键是有些语言结构需要常量:

  • case子句的值
  • 属性
  • 不变的地方和田野

常数对可达性分析有影响:

if (0 == 0) 
  M(out x); // always reached, so x is initialized 
else
  M(out y); // unreachable, so y is not initialized.

现在,让我们假设我们接受null在属性和case null中是有用的,尽管这有点奇怪,

if (null == null)

应该被视为常数true。那么,你的建议是说null在这三种方式中都是常数,但不能分配给const局部或域???这是一个奇怪的限制;如果null在其他所有需要常数的情况下都可以被视为常数,那么为什么在定义域或局部时不应该将其视为常数呢?

但我当然还没有回答你的实际问题,那就是"这什么时候有用?"

好吧,再一次,让我们后退。任何常量何时有用?编译器对待常量时,就好像它们的值被替换为它们的用法一样,那么你为什么要说:

const int Blah = 0;
...
if (x == Blah)

当你可以简单地说

if (x == 0) 

当我这样说的时候,我希望理由是显而易见的。使用任何常量字段或local的原因是为值命名,以便代码的读者更好地理解它。空常量字段或局部字段完全相同。可以说读起来更清楚:

if (node != Empty)
    stack.Push(node.Right);

if (node != null)
    stack.Push(node.Right);

Eric Lippert说,默认情况下,功能是不实现的,每种可能性都会增加测试、维护等方面的工作量。为什么引用类型的null值需要作为常量?

实现"任何实例字段都可以标记为const"的功能比实现"如果存在任何该类型的非null编译时文字,则任何实例字段可以标记为const"的功能更容易。

您实际上是在建议添加一个功能,该功能说:"如果没有该类型的非null编译时文字,则字段不能标记为const。"默认情况下,该功能未实现,如果添加该功能,将增加测试、维护等方面的工作量。

在大多数情况下,我会说只是没有
我能看到这样有用的东西的唯一情况是在预处理器条件内。例如:

#if DEBUG
const Object obj = "Debug text";
#else
const Object obj = null;
#endif

对于null具有特殊含义的(通常是递归的)数据结构,它是有意义的,而不是(或除了)通常的含义。

例如,实现了一个集合,其中null表示空集合。将集合实现为二进制搜索树的链表将使这成为一件自然的事情。在这种情况下,定义const Set Empty = null会有一些意义。经常与滥用运算符重载和大量静态方法一起出现。

这种做法符合理论计算机科学中经常使用的惯例,可以被视为理论渗透到实践中。

这是否是一件好事(tm)是另一回事,但它确实发生了。

有一种非常常见的哨兵值模式,其中一些"特殊"实体用作"终止循环"操作。我可以将以下内容视为此类代码的合理常量(请注意,显然样本是非常人为的,有一些真正的算法依赖于sentinel):

 const Item ItemLookpupSentinel = null; 
 Item Serach(IEnumerable<Item> items)
 {
       var sequenceWithSentinel = 
          items.Concat(Enumerable.Repeat(ItemLookpupSentinel, 1));
       foreach(var item in  sequenceWithSentinel )
       {
             if (item == ItemLookpupSentinel)
                return null;
       }
 }

一个有用的引用类型常量的例子是:

const string UsefulSite = "http://stackoverflow.com";

仅仅因为将null分配给常量而禁止引用类型常量不是很有用,似乎也不是很合适。值类型常量也可能非常无用:

const int FourtyTwo = 42;

这取决于你如何充分利用C#提供给你的可能性。

正如@Brian所指出的,来自评论:

希望能够将null视为const的一个原因是,您可以提供一个默认为null的可选参数(对于引用类型)。这不是一个合理的特性(C#1.0中不存在默认参数),但它现在支持将引用类型声明为const(为了一致性)。