Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are we allowed to use const with reference types if we may only assign null to them?

Tags:

c#

constants

The question is actually very straightforward. The following code throws the exception right below it:

class Foo
{
    public const StringBuilder BarBuilder = new StringBuilder();
    public Foo(){

    }
}

Error:

Foo.BarBuilder' is of type 'System.Text.StringBuilder'. A const field of a reference type other than string can only be initialized with null.

MSDN says this, which I understand and it makes sense from const perspective:

A constant expression is an expression that can be fully evaluated at compile time. Therefore, the only possible values for constants of reference types are string and a null reference.

However, I don't see the reason why or where we would use null constant. So why in the first place that a reference type (other than string) can be defined with const if it can be only set to null and if it was a deliberate decision (which I believe it is) then where can we use constant with null values?

Update:

When we think of an answer, please let's think differently than "We have this so why not that..." context.

like image 710
Tarik Avatar asked Dec 30 '14 05:12

Tarik


People also ask

What is the use of const in C#?

The const (read: constant) keyword in C# is used to define a constant variable, i.e., a variable whose value will not change during the lifetime of the program. Hence it is imperative that you assign a value to a constant variable at the time of its declaration.

What is const in unity?

A const variable is one whose value cannot be changed. A static variable is one that is available from the class itself rather than any object (these are used like global variables for most purposes). A const value has no memory management overhead, since it never needs to be collected.

What is const String?

String constants, also known as string literals, are a special type of constants which store fixed sequences of characters. A string literal is a sequence of any number of characters surrounded by double quotes: "This is a string."


Video Answer


2 Answers

However, I don't see the reason why or where we would use null constant.

Null constants are useful as sentinel values.

For example, this:

public class MyClass
{
    private const Action AlreadyInvoked = null;

    private Action _action;

    public MyClass(Action action) {
        _action = action;
    }

    public void SomeMethod()
    {
        _action();

        _action = AlreadyInvoked;
    }

    public void SomeOtherMethod()
    {
        if(action == AlreadyInvoked)
        {
            //...
        }
    }
}

Is much more expressive than this:

public class MyClass
{
    //...

    public void SomeMethod()
    {
        _action();

        _action = null;
    }

    public void SomeOtherMethod()
    {
        if(action == null)
        {
            //...
        }
    }
}

The source code for the Lazy<T> class shows Microsoft used a similar strategy. Although they used a static readonly delegate that can never be invoked as a sentinel value, they could have just used a null constant instead:

static readonly Func<T> ALREADY_INVOKED_SENTINEL = delegate
{
    Contract.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked.");
    return default(T);
};
like image 106
dcastro Avatar answered Oct 06 '22 01:10

dcastro


As you state in the question, there is one reference type that can be put into a const reference - strings. The compiler special-cases this and puts the strings into the compiled output and allows them to be read into the reference type at runtime.

Of course this begs the question - why not have strings be the only reference types that can be const, as long as we're special-casing them anyway? To that, I can only speculate that adding a special case in the compiler is simpler and less problematic than adding a special case in the language. From a language perspective, a string is just a reference type, even if the compiler has special handling to create instances of it from string literals and compiled resources.

like image 43
Avner Shahar-Kashtan Avatar answered Oct 05 '22 23:10

Avner Shahar-Kashtan