0

为什么有人会这样做:

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

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

4

7 回答 7

4

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

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

您实质上是在提议添加一个功能,即“不能将字段标记为const好像没有该类型的非空编译时文字。” 该功能默认情况下未实现,如果添加,将增加测试、维护等方面的工作量。

于 2013-12-13T20:05:18.613 回答
4

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

让我们从问一个更一般的问题开始:“C# 1.0 编译器是否应该将引用类型的 null 文字分类为常量?” 我想强调的是,我们在这里推理的是 C# 1.0,因此您不会考虑任何关于可空值类型或泛型的问题。

那么,将任何事物归类为常数有什么意义呢?关键是某些语言结构需要常量:

  • 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)

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

但当然我还没有回答你的实际问题,即“这什么时候有用?”

好吧,再一次,让我们推回去。什么时候常数有用?编译器将常量视为它们的值被替换为它们的用法,所以你为什么要说:

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

当你可以简单地说

if (x == 0) 

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

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

if (node != null)
    stack.Push(node.Right);
于 2013-12-15T17:07:24.677 回答
1

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

#if DEBUG
const Object obj = "Debug text";
#else
const Object obj = null;
#endif
于 2013-12-13T20:01:32.923 回答
1

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

例如,实现的集合 wherenull表示空集合。将集合实现为二叉搜索树的链表将使这成为一件很自然的事情。在这种情况下,定义const Set Empty = null将是有意义的。经常与滥用运算符重载以及大量静态方法一起出现。

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

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

于 2013-12-13T20:01:43.083 回答
1

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

 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;
       }
 }
于 2013-12-13T20:03:42.407 回答
1

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

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

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

const int FourtyTwo = 42;

充分利用 C# 为您提供的可能性取决于您。

于 2013-12-13T20:08:23.050 回答
0

正如@Brian 指出的那样,从评论中:

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

于 2013-12-18T15:58:55.947 回答