Immutable local values in c# - a specific use case

Viewed 379

I know that this general topic has been discussed here before. What I am interested in is if there is a good solution for my specific case:

I have a command line tool like this (simplified):

static void Main(string[] args)
{
    if (args.Length < 2)
    {
        Console.WriteLine("Usage: MyTool <InputFolder> <OutputFolder>");
        return;
    }

    string inputFolder = args[0];
    string outputFolder = args[1];

    // ...
}

I assign names to the argument values to make the code more readable. I would also like to express that these values will not be modified later.

Neither const nor readonly can be used here because the values is not known at compile time and because they are local 'variables' and not class members.

So how could I make this code more expressive and readable?

5 Answers

My proposition is creating a class holding your variables

public class Immutable
{
    public Immutable(string[] args)
    {
         InputFolder = args[0];
         OutputFolder = args[1];
    }
    public readonly string InputFolder;
    public readonly string OutputFolder;
}

then

var m = new Immutable(args)

How about the C# 7.2 ref readonly?

static void Main(string[] args)
{
    if (args.Length < 2)
    {
        Console.WriteLine("Usage: MyTool <InputFolder> <OutputFolder>");
        return;
    }

    ref readonly var inputFolder = ref args[0];
    ref readonly var outputFolder = ref args[1];
}

You could create some sort of Inputs class where you could parse the array into its parts and make the properties that expose the parsed values readonly. Simple Example:

public class Inputs {
    private string[] _args;

    public string InputFolder { get { return _args[0]; } }
    public string OutputFolder { get { return _args[1]; } }

    public Inputs(string[] args) { _args = args.Clone(); }

}

I'd do something like this:

public class ImmutableObject
{
    public ImmutableObject(string inputFolder, string outputFolder)
    {
        InputFolder = inputFolder;
        OutputFolder = outputFolder;
    }

    public string InputFolder {get;}
    public string OutputFolder {get;}
 }

static void Main(string[] args)
{
    if (args.Length < 2)
    {
        Console.WriteLine("Usage: MyTool <InputFolder> <OutputFolder>");
        return;
    }

    var folders = new ImmutableObject(args[0], args[1]);

    // ...
}

You are talking about local variables.
string is already immuttable type. Values of inputFolder and outputFolder will never changes. Of course you can assign new values to it, but you are inside one method, how big this method should be that you forget to not assign new values to it.

If values are going to be passed to other methods, they will be passed as copies, so what happen inside a method will not affect actual values of inputFolder and outputFolder.

If you still insist to have those values immutable, than consider using of types designed to be immutable.

Value tuples

(Input string, Output string) folders = (args[0], args[1]);

// Usage
folders.Input
folders.Output  

Or immutable dictionary (requires System.Collections.Immutable NuGet package)

var folders = 
    new ImmutableDictionary<string, string>().Add("input", args[0])
                                             .Add("output", args[1]);

// Usage
folders["input"]
folders["output"]
Related