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.
c# constructor compiler-errors readonly local-functions
|
show 2 more comments
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
6
The compiler turns theSetI
local function into a separate class-level method. Since this separate class-level method is not a constructor, you are not allowed to assign toreadonly
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 makeSetI
return the desired value instead of assigning it directly, or use anout
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
|
show 2 more comments
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
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
c# constructor compiler-errors readonly local-functions
edited 13 hours ago
Kris Harper
2,99152865
2,99152865
asked 15 hours ago
iliasilias
1,20421729
1,20421729
6
The compiler turns theSetI
local function into a separate class-level method. Since this separate class-level method is not a constructor, you are not allowed to assign toreadonly
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 makeSetI
return the desired value instead of assigning it directly, or use anout
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
|
show 2 more comments
6
The compiler turns theSetI
local function into a separate class-level method. Since this separate class-level method is not a constructor, you are not allowed to assign toreadonly
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 makeSetI
return the desired value instead of assigning it directly, or use anout
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
|
show 2 more comments
1 Answer
1
active
oldest
votes
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.
Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.
– ilias
11 hours ago
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.
– ilias
11 hours ago
add a comment |
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.
Thanks @canton7, I am looking forward to the c#7/8 language specification when/if it arrives.
– ilias
11 hours ago
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 toreadonly
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 anout
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