Simplifying multiple ifs dealing with flag enum
I have some code lik开发者_运维百科e this:
[Flags]
public enum someEnumFlag : long
...
if (someFlagEnum)
if (!foo()) return;
if (someFlagEnum)
if (!bar()) return;
// repeat similar lines...
For each someFlagEnum
, some method is called and it returns a bool
. If any of return values is false
, the entire operation fails. Therefore return
.
How can I simplify this? I want that "premature return" part intact, so I don't think foreach
is viable here. (Correct me if I'm wrong)
Note: This someFlagEnum
is very large (20+ flags).
Edited code. Yes, that enum is really System.Enum
.
if (
(someFlagEnum1 && !foo1()) ||
(someFlagEnum2 && !foo2()) ||
(someFlagEnum3 && !foo3()) ||
(someFlagEnum4 && !bar4()) ||
(someFlagEnum5 && !bar5()) ||
(someFlagEnum6 && !bar6()) ||
(someFlagEnum7 && !bar7()) ||
(someFlagEnum8 && !bar8())
)
{
return;
}
Simpler and more unreadable! The road to obfuscated C# starts here! :-) :-)
Second solution (C# 4.0, adaptable to other variants):
var conditions = new Tuple<Func<bool>, Func<bool>>[] {
new Tuple<Func<bool>, Func<bool>>(() => someFlagEnum.flag1, () => foo1()),
new Tuple<Func<bool>, Func<bool>>(() => someFlagEnum.flag2, () => foo2()),
new Tuple<Func<bool>, Func<bool>>(() => someFlagEnum.flag3, () => foo3()),
new Tuple<Func<bool>, Func<bool>>(() => someFlagEnum.flag4, () => foo4()),
new Tuple<Func<bool>, Func<bool>>(() => someFlagEnum.flag5, () => foo5())
}
foreach (var cond in conditions) {
if (cond.Item1() && !cond.Item2()) {
return;
}
}
If you have a lot of these flagenum values and corresponding function calls, you could reduce the code size and execution time using a dictionary lookup as a sparse array:
// set this up in advance of evaluation. Reuse across multiple evals
var lookup = new Dictionary<int, Func<bool>>();
lookup.Add(flag1, () => foo());
lookup.Add(flag2, () => bar());
lookup.Add(flag1 | flag2, () => foo() && bar());
// etc...
For each combination of flags, you add a lambda function that calls each of the corresponding functions and returns the logical and of their results, with boolean short circuit evaluation. It's a little bit cumbersome to build, but the payoff is in the evaluation:
// on evaluation, do this:
var func = lookup[someFlagEnum]; // all bits considered at the same time
if (!func()) // all (and only) the corresponding test functions called together
return;
There is a small amount of overhead for the hash lookup and anonymous function call, but if you have a lot of flags that you're testing and calling functions for, I would expect this lookup approach to perform better than piles of if statements or one if statement with a very large expression, and faster than looping through all the bits one at a time. You'll need to do some performance measurement to see where the tipping point is, but I would expect it could be as low as 6 or 7 flags (iow, lookup may be faster than performing 6 or 7 separate tests)
精彩评论