Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set readonly fields in a constructor local function c#

The following does not compile.

public class A
{
    private readonly int i;

    public A()
    {
        void SetI()
        {
            i = 10; 
        }

        SetI();
    }
}

It fails with this error:

CS0191 A readonly field cannot be assigned to (except in a constructor or a variable initializer)

Technically are we not in the constructor still, since the visibility of the local function is limited, so I'm wondering why this does not compile.

like image 849
ilias Avatar asked Mar 15 '19 11:03

ilias


People also ask

Can readonly be set in constructor?

In a field declaration, readonly indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class. A readonly field can be assigned and reassigned multiple times within the field declaration and constructor.

How do you assign a value to readonly?

You can use readonly to set the read-only attribute for the variables specified by name. A variable with the read-only attribute cannot have its value changed by a subsequent assignment and cannot be unset. Note that qsh can change the value of a variable with the read-only attribute.

How do you declare a read-only variable in C#?

In C#, you can use a readonly keyword to declare a readonly variable. This readonly keyword shows that you can assign the variable only when you declare a variable or in a constructor of the same class in which it is declared.

Can readonly be modified?

A read-only input field cannot be modified (however, a user can tab to it, highlight it, and copy the text from it). The readonly attribute can be set to keep a user from changing the value until some other conditions have been met (like selecting a checkbox, etc.).


1 Answers

The compiler turns the SetI local function into a separate class-level method. Since this separate class-level method is not a constructor, you are not allowed to assign to readonly fields from it.

So the compiler takes this:

public class A
{
    private readonly int i;

    public A()
    {
        void SetI()
        {
            i = 10; 
        }

        SetI();
    }
}

and turns it into this:

public class A
{
    private readonly int i;

    public A()
    {
        <.ctor>g__SetI|1_0();
    }

    [CompilerGenerated]
    private void <.ctor>g__SetI|1_0()
    {
        i = 10;
    }
}

(SharpLab. I left off the readonly so it would compile.)

As you can see, it's trying to assign i from the method <.ctor>g__SetI|1_0(), which isn't a constructor.

Unfortunately the C# 7.0 language specification hasn't yet been published, so I can't quote it.

Exactly the same happens if you try and use a delegate:

public class A
{
    private readonly int i;

    public A()
    {
        Action setI = () => i = 10;

        setI();
    }
}

Gets compiled to:

public class A
{
    private readonly int i;

    public A()
    {
        Action action = <.ctor>b__1_0;
        action();
    }

    [CompilerGenerated]
    private void <.ctor>b__1_0()
    {
        i = 10;
    }
}

(SharpLab, again without the readonly.)

... which likewise fails to compile.

like image 178
canton7 Avatar answered Oct 21 '22 21:10

canton7