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?
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.)
See more on this question at Stackoverflow