I currently know of two ways to make an instance immutable in C#:
void Foo()
{
// Will be serialized as metadata and inserted
// as a literal. Only valid for compile-time constants
const int bar = 100;
}
class Baz
{
private readonly string frob;
public Baz()
{
// Can be set once in the constructor
// Only valid on members, not local variables
frob = "frob";
}
}
It would be nice to have a guarantee that, some instance, once instantiated, will not be changed. const
and readonly
do this to a small degree, but are limited in their scope. I can only use const
for compile-time constants, and readonly
for member variables.
Is there any way to give a local variable immutability after its initial instantiation (the way readonly
works, but on a more general level)?
Scala does this with the var
keyword, which declares a new immutable value, which cannot be reassigned to after it gets its initial value:
var xs = List(1,2,3,4,5) // xs is a value - cannot be reassigned to
xs = List(1,2,3,4,5,6); // will not compile
You can't prevent variables from being re-assigned in C# with the exception of fields, by as you have already mentioned using const
or readonly
.
You could make your own immutable version of any existing mutable type by wrapping it or if it's your own class, re-write it to be immutable but you can't achieve it for variables in a method which is what your question seems to be getting at.
F# has a few options for immutability (the 'let
keyword if I'm remembering correctly) that C# doesn't so it might be worth looking at F# if you still want to leverage the power of .NET but with complete immutability.
If the wrapper is static it cannot be overwritten. This does sacrafice compile time checking on variable names and type safety.
public static class ReadOnly
{
private static readonly Dictionary<string, object> values = new Dictionary<string, object>();
public static bool SetValue(string name, object data)
{
if (values.ContainsKey(name))
return false;
values[name] = data;
return true;
}
public static object GetValue(string name)
{
return values[name];
}
}
ReadOnly.SetValue("xs", 1);
ReadOnly.SetValue("xs", 1); // will crash
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With