Question

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?

Was it helpful?

Solution

Servy's point is a good one. 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?" 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.

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

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??? 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?

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

OTHER TIPS

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?

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".

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." That feature is unimplemented by default and would add more effort in testing, maintaining, etc. if added.

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.

For example, a set implemented where null means the empty set. 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. 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.

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. 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.

From comments, as @Brian points out:

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. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top