I'm trying to write a method that takes references to boolean flags and modify them. The booleans are all declared separately (i.e. not in an indexable data structure) and the caller of the method should be able to decide which booleans are being modified.
Example code (this works):
class Program
{
private static bool b1, b2, b3, b4, b5;
private static void doSomething(ref bool setTrue, ref bool setFalse, ref bool invert)
{
setTrue = true;
setFalse = false;
invert = !invert;
}
static void Main(string[] args)
{
Console.WriteLine("Pre: {0}, {1}, {2}, {3}, {4}", b1, b2, b3, b4, b5);
doSomething(ref b1, ref b3, ref b5);
Console.WriteLine("Post: {0}, {1}, {2}, {3}, {4}", b1, b2, b3, b4, b5);
}
}
Output, as expected:
Pre: False, False, False, False, False
Post: True, False, False, False, True
So far, so good. Now these parameters should be optional on the method. That is, the caller can choose to e.g. use the setTrue
and the invert
effect, but not the setFalse
one.
Basically, what I'd like to do is this:
doSomething(ref b1, null, ref b5); // error CS1503: Argument 2: cannot convert from '<null>' to 'ref bool'
And then declare the doSomething
method like this:
private static void doSomething(ref bool setTrue, ref bool setFalse, ref bool invert)
{
if(setTrue != null) setTrue = true;
if(setFalse != null) setFalse = false;
if(invert != null) invert = !invert;
}
Note that I do not want to check if the value is null. The values are real bools and can't be null (and declaring them as bool?
doesn't really solve my problem). I only want to give the caller the ability to give null as the reference.
While the implementation of the method may be more complex, I'd really like to keep the invocation down to one line. (I.e. avoid having to declare temporary variables just for this call.)
One possibility would be to declare (eight) overloads for the function with all combinations of bools given or not, but then I need to come up with some scheme to make sure they all have unique signatures. (I'm stuck with C# 3.0, so no named parameters.)
Am I missing something? Is there a clean workaround? Currently the only (barely) acceptable alternative I can think of is to pass in strings with the variable names (or null) and then resolve these to the actual field using reflection.
PS: As you're probably wondering why I trying to do something this strange, some words of background: the doSomething
method is part of a library. The invocations of doSomething
are coming from generated C# code. And yes, having all these bools (~200 in the real project) as separate fields does make sense in the big picture, but the reasoning isn't really relevant for this question.
UPDATE...
If you need to potentially manipulate all three fields in a single method call then I think you'll need to use reflection to do it relatively cleanly. This can, however, be done with some degree of type-safety using expression trees; you don't need to resort to passing in the field names as strings.
DoSomething(() => b1, () => b3, () => b5);
DoSomething(() => b1, null, () => b5);
// ...
public static void DoSomething(Expression<Func<bool>> trueFieldSelector,
Expression<Func<bool>> falseFieldSelector,
Expression<Func<bool>> invertFieldSelector)
{
FieldInfo fieldInfo;
object obj;
if (GetInfo(trueFieldSelector, out fieldInfo, out obj))
fieldInfo.SetValue(obj, true);
if (GetInfo(falseFieldSelector, out fieldInfo, out obj))
fieldInfo.SetValue(obj, false);
if (GetInfo(invertFieldSelector, out fieldInfo, out obj))
fieldInfo.SetValue(obj, !(bool)fieldInfo.GetValue(obj));
}
private static bool GetInfo(Expression<Func<bool>> fieldSelector,
out FieldInfo fieldInfo, out object obj)
{
if (fieldSelector == null)
{
fieldInfo = null;
obj = null;
return false;
}
var me = fieldSelector.Body as MemberExpression;
if (me == null)
throw new ArgumentException("Select a field!", "fieldSelector");
fieldInfo = me.Member as FieldInfo;
if (fieldInfo == null)
throw new ArgumentException("Select a field!", "fieldSelector");
var ce = me.Expression as ConstantExpression;
obj = (ce == null) ? null : ce.Value;
return true;
}
Note that using reflection like this will be relatively slow. If it's not fast enough then you might need to dive a bit deeper into reflection, possibly using DynamicMethod
to create delegates and then cache them in a dictionary for re-use. (Though I wouldn't bother with that unless you're sure that plain reflection is holding you back.)
ORIGINAL ANSWER...
Wouldn't it be a lot cleaner to have separate methods and just call them as needed rather than attempting to roll it all into a single method?
SetTrue(ref b1);
SetFalse(ref b3);
Invert(ref b5);
// ...
public static void SetTrue(ref bool field)
{
DoCommonStuff();
field = true;
}
public static void SetFalse(ref bool field)
{
DoCommonStuff();
field = false;
}
public static void Invert(ref bool field)
{
DoCommonStuff();
field = !field;
}
private static void DoCommonStuff()
{
// ...
}
I'm assuming that there is some common stuff that also needs doing. If not then it would be much cleaner to simply do b1 = true
, b2 = false
, b3 = !b3
etc directly and avoid the method calls altogether.