Set readonly fields in a constructor local function c#












10















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.










share|improve this question




















  • 6





    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.

    – canton7
    15 hours ago






  • 6





    @canton7 that is the answer. Why not write it as one?

    – Jamiec
    15 hours ago











  • If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

    – Andy G
    15 hours ago











  • Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

    – Thomas Hilbert
    15 hours ago






  • 2





    There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

    – Jeroen Mostert
    15 hours ago


















10















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.










share|improve this question




















  • 6





    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.

    – canton7
    15 hours ago






  • 6





    @canton7 that is the answer. Why not write it as one?

    – Jamiec
    15 hours ago











  • If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

    – Andy G
    15 hours ago











  • Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

    – Thomas Hilbert
    15 hours ago






  • 2





    There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

    – Jeroen Mostert
    15 hours ago
















10












10








10








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.










share|improve this question
















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.







c# constructor compiler-errors readonly local-functions






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 13 hours ago









Kris Harper

2,99152865




2,99152865










asked 15 hours ago









iliasilias

1,20421729




1,20421729








  • 6





    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.

    – canton7
    15 hours ago






  • 6





    @canton7 that is the answer. Why not write it as one?

    – Jamiec
    15 hours ago











  • If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

    – Andy G
    15 hours ago











  • Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

    – Thomas Hilbert
    15 hours ago






  • 2





    There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

    – Jeroen Mostert
    15 hours ago
















  • 6





    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.

    – canton7
    15 hours ago






  • 6





    @canton7 that is the answer. Why not write it as one?

    – Jamiec
    15 hours ago











  • If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

    – Andy G
    15 hours ago











  • Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

    – Thomas Hilbert
    15 hours ago






  • 2





    There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

    – Jeroen Mostert
    15 hours ago










6




6





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.

– canton7
15 hours ago





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.

– canton7
15 hours ago




6




6





@canton7 that is the answer. Why not write it as one?

– Jamiec
15 hours ago





@canton7 that is the answer. Why not write it as one?

– Jamiec
15 hours ago













If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

– Andy G
15 hours ago





If you could do this then the variable could no longer be called readonly. By definition, it can only be set once, during construction or with an initializer.

– Andy G
15 hours ago













Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

– Thomas Hilbert
15 hours ago





Probably the local method could be called using reflection, which might allow modification of the readonly field after construction, so that's why they forbid it..?

– Thomas Hilbert
15 hours ago




2




2





There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

– Jeroen Mostert
15 hours ago







There are two obvious workarounds if you do want this, incidentally: either make SetI return the desired value instead of assigning it directly, or use an out parameter. Both involve still doing the actual assignments in the constructor itself, of course. Because local functions are documented to be private methods, just with different scope rules, this is somewhat consistent. It would not technically be possible for C# to support this without a (rather obnoxious) change in the runtime to establish a "readonly path" of callers -- not really worth it.

– Jeroen Mostert
15 hours ago














1 Answer
1






active

oldest

votes


















16














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 with the readonly.)



... which likewise fails to compile.






share|improve this answer


























  • Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

    – ilias
    11 hours ago













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55181639%2fset-readonly-fields-in-a-constructor-local-function-c-sharp%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









16














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 with the readonly.)



... which likewise fails to compile.






share|improve this answer


























  • Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

    – ilias
    11 hours ago


















16














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 with the readonly.)



... which likewise fails to compile.






share|improve this answer


























  • Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

    – ilias
    11 hours ago
















16












16








16







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 with the readonly.)



... which likewise fails to compile.






share|improve this answer















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 with the readonly.)



... which likewise fails to compile.







share|improve this answer














share|improve this answer



share|improve this answer








edited 15 hours ago

























answered 15 hours ago









canton7canton7

4,3511728




4,3511728













  • Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

    – ilias
    11 hours ago





















  • Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

    – ilias
    11 hours ago



















Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

– ilias
11 hours ago







Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.

– ilias
11 hours ago






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55181639%2fset-readonly-fields-in-a-constructor-local-function-c-sharp%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

How did Captain America manage to do this?

迪纳利

南乌拉尔铁路局