Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieving Local Runtime Immutability in C#

I currently know of two ways to make an instance immutable in C#:

Method 1 - Compile Time Immutability

void Foo() 
{
    // Will be serialized as metadata and inserted
    // as a literal. Only valid for compile-time constants
    const int bar = 100;
}

Method 2 - Readonly Fields

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
like image 626
KChaloux Avatar asked Jul 26 '13 14:07

KChaloux


2 Answers

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.

like image 76
Trevor Pilley Avatar answered Sep 21 '22 10:09

Trevor Pilley


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
like image 35
MrFox Avatar answered Sep 18 '22 10:09

MrFox