4

Bit flags are a little difficult to understand :)

I know about this and this questions and I do understand the answers and I even followed this article from a good friend of mine.

But I still cant figure it out when I need to "evolute" more than the standard...

What I'm trying to do is this:

    if (HttpContext.Current.Session["DebugSessionText"] != null)
    {
        showType = parDebug.Write2LogType.WARN | 
                   parDebug.Write2LogType.ERROR | 
                   parDebug.Write2LogType.INFO;

        if (!chkInfo.Checked)
            showType &= ~parDebug.Write2LogType.INFO;  // remove INFOs        
        if (!chkError.Checked)
            showType &= ~parDebug.Write2LogType.ERROR; // remove ERRORs

        List<myDebugRow> list =
            (List<myDebugRow>)HttpContext.Current.Session["DebugSessionText"];

        gv.DataSource = list.FindAll(x => x.Type == showType));
    }
    gv.DataBind();

I do need to filter a List object, so I can get just what the user wants (show only INFO errors, exception ERRORs but WARNing errrors will always be showed) ...

Is there a direct way to do this or I need to filter it manually without using the LAMBDA expression?

Thank you for all the help.

Community
  • 1
  • 1
balexandre
  • 73,608
  • 45
  • 233
  • 342
  • @balexandre: you got good answers below; for more information about bitwise operators, please see http://stackoverflow.com/questions/1537713/what-is-the-second-meaning-of-a-single-ampersand-in-c/1537772#1537772 – Rubens Farias Oct 15 '09 at 17:36

3 Answers3

10

With

x.Type == showType

you will only get the items that match all the conditions (bit flags) exactly. With

(x.Type & showType) != 0

You will find all items that have at least a 1 bit match with showType, which is probably what you want.

H H
  • 263,252
  • 30
  • 330
  • 514
  • exactly... the == will only show something if all flags were present, Thank you for the help and clarification. – balexandre Oct 15 '09 at 18:20
9

If you find these operations confusing -- and frankly, I certainly do -- then consider upping the level of abstraction. Write yourself some helper extension methods.

static WriteToLogType AddWarn(this WriteToLogType x) { return x | WriteToLogType.WARN; }
static WriteToLogType ClearWarn(this WriteToLogType x) { return x & ~WriteToLogType.WARN; }
static bool HasWarn(this WriteToLogType x) { return 0 != (x & WriteToLogType.WARN); }
// same for Error, Info
static bool HasExactly(this WriteToLogType x, WriteToLogType y) { return x == y; }
static bool HasAny(this WriteToLogType x, WriteToLogType y) { return 0 != (x & y); }
static bool HasAll(this WriteToLogType x, WriteToLogType y) { return y == (x & y); }

And now your program becomes

    showType = WriteToLogType.None.AddWarn().AddInfo().AddError();
    if (!chkInfo.Checked) showType = showType.ClearInfo();
    if (!chkError.Checked) showType = showType.ClearError();
    List<myDebugRow> list = whatever;
    gv.DataSource = list.FindAll(x => x.Type.HasAny(showType)));

Which I hope you agree is far more clear than all that bit-twiddling. But we can make this more clear still.

    showType = WriteToLogType.None.AddWarn();
    if (chkInfo.Checked) showType = showType.AddInfo();
    if (chkError.Checked) showType = showType.AddError();
    List<myDebugRow> list = whatever;
    gv.DataSource = list.FindAll(x => x.Type.HasAny(showType)));

Instead of adding a bunch of flags and then taking them away, simply don't add them in the first place.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
2
gv.DataSource = list.FindAll(x => x.Type == showType));

should be

gv.DataSource = list.FindAll(x => 0 != (x.Type & showType)));

As you don't want the Type to be exactly what showType is, right? You could manually iterate over the list and do a compare and remove what you don't need though I'm not sure it is an elegant solution.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
JB King
  • 11,860
  • 4
  • 38
  • 49
  • 1
    Excepth that c# does not do an automatic conversion form `int` (enum) to `bool`. – H H Oct 15 '09 at 17:32