开发者

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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜