Access to modified closure: ReSharper

I created a library that handles database access. I recently added transaction handling; however, I came across a small issue. To outline this, I wrote this sample for demonstration purposes:

class Program
{
    static void Main(string[] args)
    {
        String data = null;
        DoAction(ref data, () =>
        {
            Console.WriteLine(data);
        });
        Console.ReadLine();
    }

    private static void DoAction(ref String data, Action action)
    {
        if (data == null)
            data = "Initialized Data";
        action();
    }
}

I get "Access to modified closure" underline on the following code line for the 'data' variable:

Console.WriteLine(data);

I understand that the modification of the ref data variable can cause issues (e.g. when running foreach loops). However, in the following case, I don't see this to happen.

Here is another version with a loop changing the variable further - the output is as expected:

class Program
{
    static void Main(string[] args)
    {
        String data = null;
        for (var i = 0; i < 10; i++)
            DoAction(ref data, () =>
            {
                Console.WriteLine(data);
            });
        Console.ReadLine();
    }

    private static void DoAction(ref String data, Action action)
    {
        if (data == null)
            data = "Initialized Data";
        else
            data += "|";

        action();
    }
}

ReSharper offers me to create a local variable, but I explicitly want to use the created string from the DoAction() method. If I would accept ReSharpers approach, it actually would break the code. Is there any other way to solve this problem? I'd like to use this Action approach, but I don't want ReSharper to complain about it either (and possibly not disable ReSharpers inspection).

Any suggestions?

Jon Skeet
people
quotationmark

I would suggest avoid using a ref parameter for this in the first place - it seems needlessly complicated to me. I'd rewrite DoAction as:

static string DoAction(string data, Action<string> action)
{
    data = data == null ? "Initialized Data" : data + "|";
    action(data);
    return data;
}

Then you can have:

data = DoAction(data, Console.WriteLine);

or if you want to use a lambda expression:

data = DoAction(data, txt => Console.WriteLine(txt));

You can make DoAction a void method if you don't actually need the result afterwards. (It's not clear why you need the result to be returned and a delegate to execute in DoAction, but presumably that makes more sense in your wider context.)

people

See more on this question at Stackoverflow