Having a friendly debate with a co-worker about this. We have some thoughts about this, but wondering what the SO crowd thinks about this?
-
Do you any other languages have this feature? It seems obvious. – Colonel Panic Jul 07 '15 at 15:00
-
8@ColonelPanic C and C++ have const local variables, which you can initialize with a runtime-computed value. – Crashworks Jan 09 '16 at 11:08
-
5JavaScript 2015 (ES6) has const type. E.g. { const myList = [1,2,3]; }. It's very good programming practice to use this construct. More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const – andrew.fox Jan 18 '16 at 09:20
-
4**Update 2017**: Please vote for the feature request under discussion in the C# Language Design repo! https://github.com/dotnet/csharplang/issues/188 – Colonel Panic Dec 06 '17 at 10:21
-
@Crashworks It does? When I try to `const` a local var (builtin value type) in C#, I get `error CS0133: The expression being assigned to 'varName' must be constant`. – Slipp D. Thompson May 28 '21 at 11:17
-
I just got hit by a bug because this doesn't exist. Someone modified a variable that should have been a const and rekked a loop... how many thousands of hours have been lost debugging because .net does not have this simple feature? – Brain2000 Mar 01 '23 at 20:27
13 Answers
I think it's a poor judgement on part of C# architects. readonly modifier on local variables helps maintain program correctness (just like asserts) and can potentially help the compiler optimize code (at least in the case of other languages). The fact that it's disallowed in C# right now, is another argument that some of the "features" of C# are merely an enforcement of personal coding style of its creators.

- 2,118
- 3
- 22
- 28
-
16I agree on the "save the programmer from himself" part, but as for helping the compiler to optimize code, I hold the stance that the compiler can find out very well whether or not a variable changes over the course of the method and optimizes accordingly either way. Placing a 'readonly' flag before something the optimizer recognizes anyways for that purpose does not really benefit, yet potentially mislead. – Cornelius May 10 '11 at 12:37
-
2@Cornelius I agree that there are opinions that in some cases the compiler uses data-flow diagram to figure out optimization opportunity regardless of any keyword/modifiers. But **saving the programmer from himself** from writing incorrect and otherwise unnecessarily unoptimized code may open up that optimization opportunity for compiler. – KRoy Nov 16 '18 at 19:37
-
Don't modern compilers perform Static Single Assignment anyway? In which case it's moot as far as optimizations are concerned (but if a compiler supports SSA then it means it's also trivial to implement assign-once local variables). – Dai May 03 '20 at 06:59
A proposal readonly locals and parameters for was briefly discussed by the C# 7 design team. From C# Design Meeting Notes for Jan 21, 2015:
Parameters and locals can be captured by lambdas and thereby accessed concurrently, but there's no way to protect them from shared-mutual-state issues: they can't be readonly.
In general, most parameters and many locals are never intended to be assigned to after they get their initial value. Allowing readonly on them would express that intent clearly.
One problem is that this feature might be an "attractive nuisance". Whereas the "right thing" to do would nearly always be to make parameters and locals readonly, it would clutter the code significantly to do so.
An idea to partly alleviate this is to allow the combination readonly var on a local variable to be contracted to val or something short like that. More generally we could try to simply think of a shorter keyword than the established readonly to express the readonly-ness.
Discussion continues in the C# Language Design repo. Vote to show your support. https://github.com/dotnet/csharplang/issues/188

- 132,665
- 89
- 401
- 465
-
could also make readonly the default (via some option or keyword or whatever). most variables and parameters should be readonly, with only a few writable. and minimizing the number that are writable is generally a good thing. – Dave Cousineau Feb 06 '20 at 20:02
-
1
-
`const` has a very specific meaning. Using `val` (like Scala) or `let` would be a better option. – Luís Guilherme Aug 25 '22 at 14:04
-
@DaveCousineau making variables read only by default would need additional keyword (such as `mutable` in F#) to have them modifiable. I think the change would be as big as introduction of `#nullable`. – Endrju Jan 03 '23 at 19:55
Addressing Jared's answer, it would probably just have to be a compile-time feature - the compiler would prohibit you from writing to the variable after the initial declaration (which would have to include an assignment).
Can I see value in this? Potentially - but not a lot, to be honest. If you can't easily tell whether or not a variable is going to be assigned elsewhere in the method, then your method is too long.
For what it's worth, Java has this feature (using the final
modifier) and I've very rarely seen it used other than in cases where it has to be used to allow the variable to be captured by an anonymous inner class - and where it is used, it gives me an impression of clutter rather than useful information.

- 1,421,763
- 867
- 9,128
- 9,194
-
I agree with the usefulness of it. That was one of the points we hit in our discussion. If readonly is really useful, you probably need to refactor. – Brian Genisio Jan 14 '09 at 17:38
-
83There's a difference between seeing whether or not a variable is modified in your method by *sight* and by *the compiler*. I see no objection to writing a method, stating my intent to not modify a variable, and having the compiler notify me when I accidentally do (perhaps with a typo a month later)! – A. Rex Jan 14 '09 at 18:06
-
53On the other hand, in F# all variables are read-only by default, and you have to use the 'mutable' keyword if you want to be able to change them. Since F# is a .NET language, I imagine it does the compile-time checking you describe. – Joel Mueller Jan 14 '09 at 18:43
-
2@A.Rex: The question is really whether the benefit of getting the compiler to do that checking is worth the extra "fluff" when reading the code and not actually caring about it. – Jon Skeet Jan 14 '09 at 20:52
-
2Consider the following definition `int arr[] = new int[numItems];`, placed just before a loop that passes `arr` to an unfamiliar method. Even it's clear that `arr` always points to the same array, it might not be clear whether that is because there was never any need to make it point elsewhere, or because the called method relies upon its always being the same instance. That distinction may become important if e.g. future code requires that the code deal with arrays of different sizes that aren't known in advance. – supercat Nov 19 '12 at 17:57
-
Regarding `final` in Java. It **has** to be used when creating a local anonymous class which uses the externally scoped (final) variable... and for very good reason: closure. – intrepidis May 30 '13 at 20:37
-
@ChrisNash: Yes, I meant I've very rarely seen it used where it didn't have to be. Will edit to clarify that. – Jon Skeet May 30 '13 at 20:37
-
2Um, I've always used final in Java for "magic numbers", which can be scoped to the method or class. I was just trying to do the same thing in C# but apparently it isn't possible and I don't see why not given this common use case. I really feel squeamish about non-immutable magic numbers. Yes, I know I won't modify them, it just doesn't feel right. – makhdumi Jan 16 '14 at 22:49
-
@Al-Muhandis: It's not really clear what you mean. You can use `const` in a method, if that's what you want... – Jon Skeet Jan 16 '14 at 22:54
-
@JonSkeet Ah, right, what I had in mind aren't really magic numbers. e.g. `final int OffsetA = this.BaseOffset + 1412`. I could use a `const` for the `1412`, yes, but then that defeats the purpose of having a separate variable for readability. I don't want a `const` in this case, just something that's readonly, i.e. non-immutable. The implementation doesn't fit logically and it's frustrating. – makhdumi Jan 17 '14 at 01:18
-
@Al-Muhandis: Right, I'm with you (although I don't think you mean non-immutable). I can't say it's something I particularly miss - if the methods are suitably short, it's not too hard to just avoid changing the value of the variable in question. I believe there was a suggestion to have an equivalent of `var` but for a read-only variable... but I don't think it's happening. – Jon Skeet Jan 17 '14 at 06:47
-
1-1 "I'd rather not see a language feature which reduces the impact of spaghetti methods" This argument in favor of assembly language programming is absurd and, to the degree that it convinces readers, has negative value. However, the experience with corresponding feature in C++ is that it better should have been the default. – Cheers and hth. - Alf Jun 14 '14 at 13:04
-
@Cheersandhth.-Alf: I fail to see where I've advocated "assembly language programming". As I said, there's some value - but I don't think it justifies inclusion now. – Jon Skeet Jun 14 '14 at 13:10
-
1@JonSkeet: since the same argument, that a constraint on possible operations "reduces the impact of spaghetti code", applies equally to use of static typing, control flow constructs, etc. as I wrote, it's absurd. not a valid technical argument. – Cheers and hth. - Alf Jun 14 '14 at 13:26
-
@Cheersandhth.-Alf: I think "absurd" is too strong, but I agree it's not great. Will remove it. – Jon Skeet Jun 14 '14 at 13:50
-
6FWIW, Scala distinguishes local `readonly`/`final` values from variables with its `val` and `var` keywords. In Scala code, local `val`s are used *very* frequently (and are, in fact, preferred over local `var`s). I suspect that the primary reasons that the `final` modifier is not used more frequently in Java are a) clutter and b) laziness. – Aaron Novstrup Jun 20 '14 at 16:51
-
what would be nice (maybe) is if locals were readonly by default, and you had to say "writable" or something to be able to write to them again – Dave Cousineau Mar 03 '15 at 22:57
-
@Sahuagin: Indeed. There was a thought about having `val`, which would be like `var` but read-only. I think the issue is that it's a bit too close to `var`... – Jon Skeet Mar 04 '15 at 07:01
-
5For local variables that aren't used in closures, `readonly` wouldn't be overly important. On the other hand, for local variables which are used in closures, `readonly` would in many cases let the compiler generate more efficient code. Presently, when execution enters a block which contains a closure, the compiler must create a new heap object for the closed-over variables, *even if no code which would use the closure is ever executed*. If a variable were read-only, code outside the closure could use a normal variable; only when a delegate is created for the closure... – supercat Mar 04 '15 at 21:32
-
2...would it be necessary to copy the local variable into a new heap object. Further, if a method contains a lambda that uses two variables, one of which identifies a small/cheap object and the other of which identifies a big/expensive one, and a second lambda that only uses the small/cheap object, any code which keeps the latter delegate alive will also keep alive the expensive object. Declaring *either* of the references `readonly` would allow the compiler to break the connection. – supercat Mar 04 '15 at 21:38
-
2Sorry, but "the compiler would prohibit you from writing to the variable after the initial declaration" is nowhere near sufficient. Thinking about C++ const-correctness leads to some examples of the complexity: Could you pass it by reference? It's perfectly possible for a method to want a reference instead of a copy, because it needs to see changes made by callbacks. Yet parameters are visible across language boundaries, and the CLR has no syntax for marking a `ref` parameter read-only analogous to C++ `const T&`. What member functions could you use? Could you invoke property getters? – Ben Voigt Feb 26 '16 at 04:41
-
1If you make read-only shallow, then the last two questions are easy (Yes.) but surprising. And it seems likely that passing by reference would just be disallowed as it is for `initonly` fields, even though that isn't formally correct. But any such feature involves far more than just assignment. – Ben Voigt Feb 26 '16 at 04:43
-
3I'd personally love it if we could declare locals using the `let` keyword from monadic query comprehensions. same thing as `var`, only it'd be readonly. I dunno if that would make the compiler more complicated or if it might be a breaking change. – sara Jun 20 '16 at 09:04
-
1As for Java, it's no surprise that you rarely see "final" variables because it means extra typing and code clutter (I wouldn't use it either). This would be very different with using "let" keyword in C# (existing already in LINQ expressions) instead of "var". – user1414213562 Oct 17 '16 at 18:38
-
2It shouldn't be very hard to implement. Here's how to do this: - Modify Roslyn compiler so that it accepts "let" keyword everywhere where it accepts "var". Here is an example of similar compiler modification (accepting different string beginning/termination characters): https://blogs.msdn.microsoft.com/csharpfaq/2014/04/03/taking-a-tour-of-roslyn/ - Write an analyzer which gives an error when a variable declared with "let" keyword is modified (google "Roslyn analyzer") - Send both components to Microsoft ;) – user1414213562 Oct 17 '16 at 18:39
-
3The experience of writing javascript using const made me look for this in c#. I've always been missing c# features when writing javascript. This is the first time I've been missing javascript features in c#. – Sam Sippe Oct 04 '17 at 23:12
It is an oversight for c# language designer. F# has val keyword and it is based on CLR. There is no reason C# can't have the same language feature.

- 1,142
- 1
- 15
- 22
-
C# clearly needs a keyword to initialize local constants at runtime, a keyword where you can specify the type or have it be inferred like var. Except that the inferred type should be non-nullable IMO. – Rivenfall Mar 16 '23 at 14:41
One reason is there is no CLR support for a readonly local. Readonly is translated into the CLR/CLI initonly opcode. This flag can only be applied to fields and has no meaning for a local. In fact, applying it to a local will likely produce unverifiable code.
This doesn't mean that C# couldn't do this. But it would give two different meanings to the same language construct. The version for locals would have no CLR equivalent mapping.

- 733,204
- 149
- 1,241
- 1,454
-
71It actually has nothing to do with CLI support for the feature, because local variables are in no way exposed to other assemblies. The `readonly` keyword for fields needs to be supported by the CLI because its effect *is* visible to other assemblies. All it would mean is the variable only has one assignment in the method at compile time. – Sam Harwell Sep 03 '09 at 02:06
-
22I think you've just shifted the question to why the CLR does not support this rather than providing the rational behind it. It does allow for const locals, so it would be reasonable to expect readonly locals as well. – Chad Schouggins Aug 16 '12 at 16:25
-
11An example of this are variable defined in a using statement. They are local ... and readonly (try to assign them, C# will add an error). – Softlion Nov 16 '13 at 10:46
-
9-1 In C++ there's no machine code support for `const` (which in C++ is more like C# `readonly` than like C# `const`, although it can play both roles). Yet C++ supports `const` for local automatic variable. Hence the lack of CLR support for a C# `readonly` for local variable, is irrelevant. – Cheers and hth. - Alf Jun 14 '14 at 13:00
-
81. This can easily be a compiler feature, like in C++. CLR support is completely irrelevant. Machine assembly doesn't support it either, so what? 2. *(it would) likely produce unverifiable code* - I don't see how, but perhaps I am mistaken. 3. *it would give two different meanings to the same language construct* - I doubt anyone would see this as an issue, since `using` and `out` are doing exactly that and the world didn't collapse. – Lou Mar 15 '17 at 10:28
-
3Isn't a readonly **var**iable a sweet oxymoron? I vote for "immutable stack elements". =) – cubuspl42 Jul 27 '17 at 16:15
I was that coworker and it wasn't friendly! (just kidding)
I would not eliminate the feature because it's better to write short methods. It's a bit like saying you shouldn't use threads because they're hard. Give me the knife and let me be responsible for not cutting myself.
Personally, I wanted another "var" type keyword like "inv" (invarient) or "rvar" to avoid clutter. I've been studying F# as of late and find the immutable thing appealing.
Never knew Java had this.

- 301
- 3
- 10
I would like local readonly variables in the same manner as I like local const variables. But it has less priority than other topics.
Maybe its priority is the same reason for C# designers to not (yet!) implement this feature. But it should be easy (and backward compatible) to support local readonly variables in future versions.

- 4,287
- 4
- 23
- 38
I know, this doesn't answer the why to your question. Anyway, those reading this question might appreciate the code below nonetheless.
If you are really concerned with shooting your self in the foot when overriding a local variable that should only be set once, and you don't want to make it a more globally accessible variable, you could do something like this.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Example usage:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Maybe not as less code as rvar rInt = 5
but it works.

- 11,906
- 8
- 54
- 76
-
That doesn't help here. This issue with variable 'var' is: { var five = 5 five = 6; Assert.That(five==5) } – Murray May 10 '17 at 07:52
-
1
Readonly means the only place the instance variable can be set is in the constructor. When declaring a variable locally it doesn't have an instance (it's just in scope), and it can't be touched by the constructor.

- 38,967
- 12
- 96
- 122
-
9That's the current meaning of 'readonly' in C#, but that isn't the question. 'read only' has an English meaning that seems to have intuitive application to a local variable: You can't write to it (after it's been initialized). That seems very much like the meaning when applied to instance variables, so why (as in justification, I think) can't we apply it to local variables? – Spike0xff Oct 22 '15 at 21:16
You can declare readonly local variables in C#, if you're using the C# interactive compiler csi
:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
You can also declare readonly local variables in the .csx
script format.

- 132,665
- 89
- 401
- 465
-
8Per the error message, `message` is not a variable here, it's compiled to a field. This is not nitpicking because the distinction clearly exists in interactive C# as well: `int x; Console.WriteLine(x)` is legal interactive C# (because `x` is a field and implicitly initialized) but `void foo() { int x; Console.WriteLine(x); }` is not (because `x` is a variable and used before it's assigned). Also, `Expression
> y = x; ((MemberExpression) y.Body).Member.MemberType` will reveal that `x` is really a field and not a local variable. – Jeroen Mostert Jul 12 '16 at 15:32
Being able to make local variables readonly makes it a lot easier to understand complicated algorithms, since it reduces the number of moving parts.
Since C# doesn't offer it natively for non-compile time constants I use this with implicit casts:
public readonly struct ReadonlyVar<T>
{
private readonly T value;
internal ReadonlyVar(T _value) => value = _value;
public static implicit operator T(ReadonlyVar<T> _readonly) => _readonly.value;
public override string ToString() => "" + value;
}
public static class ReadonlyExt
{
public static ReadonlyVar<T> Readonly<T>(this T _value) => new ReadonlyVar<T>(_value);
}
Usage:
int y = 234;
var x = ( 9000 + y ).Readonly();
y = x;
It is not perfect, since it is possible to assign another ReadonlyVar to it, but this never happened to me unintentionally.

- 11
- 2
-
Hi Christian - I don't think this is actually an answer to the question. It seems the question is "I wonder why C# doesn't natively support this, any thoughts?" rather than a "how would one do this?" Javascript now has both a "let" and a "const", but c# has nothing equivalent to "const", and this question wonders why. – pettys Sep 13 '21 at 21:47
-
This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/29815826) – pettys Sep 13 '21 at 21:48
-
1Hi pettys, the author indeed didn't ask how do this, but this thread is the first and only on stackoverflow when I search for "c# readonly local variable". I guess that most people, like me, arrive here, because they want that feature. Since it is less than 10 lines of code, it's even less reason for Microsoft to change the compiler for a feature that might not be important in their opinion. – Christian Teister Sep 13 '21 at 22:40
-
This doesn't actually make the variable readonly at all. In your own usage code you can just write `x = 42.ReadOnly();` and you have mutated the variable. This code ads complexity without adding any actual functionality. It's also off topic to the question, as others have said, but it's not useful anyway. – Servy Sep 13 '21 at 23:11
-
1That's right, Servy. :) But so far I never happened to me unintentionally. I often make local variables readonly to make complicated algorithms easier to understand. At least for me it is a very useful tool to have. – Christian Teister Sep 14 '21 at 06:11
-
@ChristianTeister Fair point. SO asked me to review this answer, and one of the guidelines was to make sure the response answers the question. FWIW, the downvote wasn't me. – pettys Sep 14 '21 at 16:54
use const
keyword to make read only variable.
reference: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}

- 1,142
- 1
- 15
- 22
-
3We’re interested in JavaScript-style `const` where the variable may only be assigned during its initialization—not csharp-style `const` where only compile-time expressions may be used. E.g., you can’t do `const object c = new object();` but a `readonly` local would allow you to do this. – binki Dec 22 '17 at 19:10
I think that's because a function that has a readonly variable may never be called, and there's probably something about it going out of scope, and when would you need to?

- 27,829
- 22
- 107
- 159