简体   繁体   English

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

[英]Is it ever useful to have reference type declared as const?

Why would someone ever do: 为什么有人会这样做:

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

Eric Lippert says features are unimplemented by default and every possibility adds more effort in testing, maintaining etc... Why would a null value for a reference type ever needed as a constant? 埃里克·利珀特(Eric Lippert)说,默认情况下未实现功能,并且每种可能性都在测试,维护等方面增加了工作量。

Eric Lippert says features are unimplemented by default and every possibility adds more effort in testing, maintaining etc... Why would a null value for a reference type ever needed as a constant? 埃里克·利珀特(Eric Lippert)说,默认情况下未实现功能,并且每种可能性都在测试,维护等方面增加了工作量。

It was easier to implement the feature that, "any instance field can be marked as const " than to implement the feature that, "any instance field can be marked as const if there are any non-null compile time literals of that type". 实现“可以将任何实例字段都标记为const ”的功能比实现“没有任何类型的非空编译时文字可以将其实例化为const ”的功能要容易。

You're essentially proposing adding a feature that says, "a field cannot be marked as const if there are no non-null compile time literals of that type." 您实际上是在建议添加一个功能,该功能说:“如果没有该类型的非null编译时文字,则字段不能标记为const ”。 That feature is unimplemented by default and would add more effort in testing, maintaining, etc. if added. 该功能默认情况下未实现,如果添加,将在测试,维护等方面增加工作量。

Servy's point is a good one. Servy的观点很不错。 Let me explain that point in a slightly different way. 让我以稍微不同的方式解释这一点。

Let's start by asking the more general question "should the C# 1.0 compiler classify a null literal of reference type as a constant?" 让我们首先问一个更普遍的问题:“ C#1.0编译器是否应该将引用类型的空文字归为常量?” I want to emphasize that we are reasoning about C# 1.0 here, so any concerns about nullable value types or generics are not on your mind. 我想强调的是,我们在这里考虑的是C#1.0,​​因此您不必担心任何有关可空值类型或泛型的问题。

Well, what's the point of classifying anything as a constant? 那么,将任何东西归类为常量的意义何在? The point is that there are certain language constructs that require constants: 关键是某些语言构造需要常量:

  • The value of a case clause case条款的价值
  • Attributes 属性
  • Constant locals and fields 不变的当地人和领域

And constants have an effect on reachability analysis: 常量会影响可达性分析:

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

Now, let's suppose that we accept that null is useful in attributes and case null and that though it is a bit weird, 现在,假设我们接受null在属性和case null有用,尽管有点怪异,

if (null == null)

ought to be treated as the constant true. 应该被视为常数。 Your proposal then is to say that null is a constant in these three ways, but nevertheless cannot be assigned to a const local or field??? 那么您的建议是说null在这三种方式中是一个常量,但是仍然不能分配给const local或field? That is a bizarre restriction; 这是一个奇怪的限制; if null may be treated like a constant in every other situation where a constant is required, then why should it not be treated as a constant when defining a field or local? 如果在需要常量的其他所有情况下,都可以将null视为常量,那么为什么在定义字段或局部字段时不将其视为常量呢?

But of course I haven't answered your actual question, which is "when is this useful?" 但是我当然没有回答您的实际问题,即“什么时候有用?”

Well, again, let's push back. 好吧,再次让我们往回推。 When is any constant useful? 什么常量在什么时候有用? Constants are treated by the compiler as though their value is substituted into their usage, so why would you ever say: 常量被编译器视为将其值替换为它们的用法,那么为什么您会说:

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

when you could simply say 当你可以简单地说

if (x == 0) 

? When I put it like that I hope the reasoning is obvious. 当我这样说时,我希望推理是显而易见的。 The reason you use any constant field or local is to give a name to a value so that the reader of the code understands it better. 使用任何常量字段或局部变量的原因是为值赋予名称,以便代码阅读者更好地理解它。 A null constant field or local is exactly the same. 空常量字段或局部字段完全相同。 It is arguably more clear to read: 可以读得更清楚:

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

than

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

In most cases I'd say just no . 在大多数情况下,我会说不
The only case where I can see something like that useful is inside a preprocessor condition. 我可以看到类似有用的东西的唯一情况是在预处理器条件内。 For example: 例如:

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

It can make sense for (typically recursive) data structures for which null has a special meaning, other than (or in addition to) the usual. 对于(通常是递归的)数据结构,对于null具有特殊含义(而不是通常的含义)的是有意义的。

For example, a set implemented where null means the empty set. 例如,实现的集合,其中null表示空集合。 Implementing a set as a linked list of a binary search tree would make that a natural thing to do. 将集合实现为二进制搜索树的链接列表将使这很自然。 Defining const Set Empty = null would make some sense in that case. 在这种情况下,将const Set Empty = null定义会很有意义。 Often seen together with abusing operator overloading, and with an abundance of static methods. 通常与滥用操作员重载以及大量静态方法一起出现。

This practice matches conventions often used in theoretical Computer Science, it could be seen as theory leaking into practice. 这种实践符合理论计算机科学中经常使用的惯例,可以看作是理论渗入实践。

Whether that's a Good Thing (tm) or not is an other matter, but it does happen. 这是否是一件好事(tm)是另一回事,但这确实发生了。

There is pretty common sentinel value pattern where some "special" entity used as "terminate loop" operation. 有一种非常常见的哨兵价值模式,其中某些“特殊”实体用作“终止循环”操作。 I can see following as reasonable constant for such code (note that clearly sample is very contrived, there are real algorithms that rely on 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;
       }
 }

An example of a useful reference type constant is: 有用的引用类型常量的一个示例是:

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

Forbidding reference type constants just because assigning null to a constant is not very useful, seems not very appropriate. 仅仅因为将null分配给常量不是很有用,所以禁止引用类型常量,这似乎不太合适。 Value type constants can be pretty useless as well: 值类型常量也可能毫无用处:

const int FourtyTwo = 42;

It's up to you to make the best of the possibilities C# offers to you. 充分利用C#为您提供的可能性由您决定。

From comments, as @Brian points out: @Brian指出,评论来自:

One reason to want to be able to treat null as const is so that you can provide an optional argument (for reference types) defaulting to null. 希望将null视为const的一个原因是,您可以提供一个可选参数(对于引用类型),默认为null。 This isn't a justifying feature (default parameters didn't exist in C# 1.0), but it's points in favor of allowing reference types to be declared as const (for consistency) now. 这不是一个合理的功能(C#1.0中不存在默认参数),但是它支持现在允许将引用类型声明为const(出于一致性)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 什么时候在C#中有用的值类型/引用类型约束? - When is a value type / reference type constraint useful in C#? const变量会改变吗? - Will a const variable ever change? 可选参数必须是引用类型,可为空的类型,或者必须声明为可选参数 - An optional parameter must be a reference type, a nullable type, or be declared as an optional 为什么作为引用类型的字符串可以是非空const,而其他引用类型consts必须为null? - Why can string that is a reference type be a non-null const while other reference type consts must be null? const声明的变量的内存使用情况 - Memory usage by const declared variable 哪些类型可以声明为const? - What types can be declared as const? 什么时候,如果有的话,我们应该使用 const 吗? - When, if ever, should we use const? 引用类型变量回收-如果在循环中声明了每个循环,是否会在循环中的每个循环中创建新的参考变量? - Reference type variable recycling - is a new reference variable created every loop in a loop if declared therein? 可选参数必须是引用类型、可为空类型或声明为可选参数。 参数名称:参数` - An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters` 遇到错误,可选参数必须是引用类型,可为空的类型,或者必须声明为可选参数 - Getting Error An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM