Bitwise Operation...What am I doing wrong here

X

xanthviper

Hey,

I'm trying to do what I think is pretty basic here, but I am missing
something. Hopefully someone can point me in the right direction.

Essentially I have an enumeration set up as the following:

public enum DocumentFlags
{

Enabled = 1,
Accepted = 2,
Denied = 4,
Deleted = 8,

TDB_Available = 16

};


Those values, when added up, will go into an INT field (called FLAGS)
on a SQL 2000 DB. So for instance if I work with the values of
TDB_Available and Enabled, I would put 17 within the database.

This works fine if I do my sql queries trying to match specific values
and so forth.


Unfortunately, I can't figure out how to properly determine what values
were inserted into the database field (FLAGS).

Essentially I want to, in C# on my ASP.NET project, I want to get that
17 value back, and then determine if in fact TDB_Available is within
that value?

I would love to just have a function that would basically do:

private bool IsFlagTrue(int FLAG, int CheckValue)
{

return true/false;

}

I appreciate you taking the time to check this out.
 
J

Jon Skeet [C# MVP]

public enum DocumentFlags
{

Enabled = 1,
Accepted = 2,
Denied = 4,
Deleted = 8,

TDB_Available = 16

};

<snip>

Firstly, if that's a flags enum, it's worth using the FlagsAttribute:

[Flags]
public enum DocumentFlags (etc)
I would love to just have a function that would basically do:

private bool IsFlagTrue(int FLAG, int CheckValue)
{

return true/false;

}

I appreciate you taking the time to check this out.

Well, you can use:

return (CheckValue & Flag) != 0;

I would personally use a more strongly typed version though:

private bool IsFlagSet (DocumentFlags flag, DocumentFlags value)
{
return ((int)flag & (int)value)!=0;
}
 
X

xanthviper

Hi Jon,

Thank you for your help. After I posted this, I realized that I needed
to set up my values a little more properly. So here is what I have:

[Flags()]
public enum DocumentFlags : int
{
None = 0,
Enabled = 1,
Accepted = 2,
Denied = 4,
Deleted = 8,

TDB_Available = 16
};


Then on my ASP Function I work with the following:

dtrDocInfo is a DataReader

lblBlahText = IsFlagSet(Convert.ToInt32(dtrDocInfo["DocumentFlag"]),
Convert.ToInt32(DocumentFlags.Enabled)).ToString();

And then the IsFlagSet function looks like:

private bool IsFlagSet(int DocFlag, int CheckValue)
{
return (CheckValue & DocFlag) != 0;
}


That works. I'm happy with it. However, I would much rather do it your
way as that looks to me to be the proper way of doing things. Any
suggestions as to where I could modify this to work in the "proper"
way?

Thanks :)
 
M

Mythran

Hey,

I'm trying to do what I think is pretty basic here, but I am missing
something. Hopefully someone can point me in the right direction.

Essentially I have an enumeration set up as the following:

public enum DocumentFlags
{

Enabled = 1,
Accepted = 2,
Denied = 4,
Deleted = 8,

TDB_Available = 16

};


Those values, when added up, will go into an INT field (called FLAGS)
on a SQL 2000 DB. So for instance if I work with the values of
TDB_Available and Enabled, I would put 17 within the database.

This works fine if I do my sql queries trying to match specific values
and so forth.


Unfortunately, I can't figure out how to properly determine what values
were inserted into the database field (FLAGS).

Essentially I want to, in C# on my ASP.NET project, I want to get that
17 value back, and then determine if in fact TDB_Available is within
that value?

I would love to just have a function that would basically do:

private bool IsFlagTrue(int FLAG, int CheckValue)
{

return true/false;

}

I appreciate you taking the time to check this out.

public static bool IsFlagSet(DocumentFlags Flag, DocumentFlags Value)
{
return ((Flag & Value) == Value);
}

public static DocumentFlags SetFlag(DocumentFlags Flag, DocumentFlags Value)
{
return (Flag | Value);
}

public static DocumentFlags RemoveFlag(DocumentFlags Flag, DocumentFlags
Value)
{
if (IsFlagSet(Flag, Value)) {
return ToggleFlag(Flag, Value);
}

return Flag;
}

public static DocumentFlags ToggleFlag(DocumentFlags Flag, DocumentFlags
Value)
{
return (Flag ^ Value);
}

DocumentFlags flag = 0;

flag = SetFlag(flag, DocumentFlags.Deleted);
flag = RemoveFlag(flag, DocumentFlags.Accepted);

et cetera :)

Mythran


HTH,
Mythran
 
J

Jon Skeet [C# MVP]

Thank you for your help. After I posted this, I realized that I needed
to set up my values a little more properly. So here is what I have:

[Flags()]

No need for the brackets - just
[Flags]

Then on my ASP Function I work with the following:

dtrDocInfo is a DataReader

lblBlahText = IsFlagSet(Convert.ToInt32(dtrDocInfo["DocumentFlag"]),
Convert.ToInt32(DocumentFlags.Enabled)).ToString();

I'd suggest either just casting to int, or using dtrDocInfo.GetInt32
instead - much nicer than those calls to Convert.ToInt32. Mind you,
just putting things in separate lines may well help matters :)
And then the IsFlagSet function looks like:

private bool IsFlagSet(int DocFlag, int CheckValue)
{
return (CheckValue & DocFlag) != 0;
}


That works. I'm happy with it. However, I would much rather do it your
way as that looks to me to be the proper way of doing things. Any
suggestions as to where I could modify this to work in the "proper"
way?

Well, in this case I'm not sure there'd be any benefit in casting the
value to a DocumentFlags, but you could make the method take the (in
this case constant) flag it's meant to check as a DocumentFlags:

private bool IsFlagSet (DocumentFlags docFlag, int checkValue)
{
return ((int)docFlag & checkValue) != 0;
}

(Note that according to the MS conventions which are widely used,
parameters are camel-cased - the first letter is lower-case.)
 
X

xanthviper

Mythran,

Thank you for your help. I know exactly what it is you are doing here,
essentially working with 001101 and the like. (At risk of sounding
like an idiot here) I think if I had originally set up my database to
work like that, then I think I would have found an answer to all of
this pretty fast as that is what has been available out on the web.
Thank you though. I do appreciate your time in answering this.

XV
 
X

xanthviper

Jon,

Thanks for your assistance on this. In the end, I ended up doing this:



lblPermission.Text = IsFlagSet2(DocumentFlags.Enabled,
dtrDocInfo.GetInt32(dtrDocInfo.GetOrdinal("DocumentFlag"))).ToString();



private bool IsFlagSet2(DocumentFlags docFlag, int checkValue)
{
return ((int)docFlag & checkValue) != 0;
}




On a side note: I am properly using camel-cased, just didn't do it when
I was writing here. Thanks for making sure I'm doing it correctly
though :)

- XV
 
G

Guest

From a database perspective it may be worth your while to store the flags in
seperate fields - makes for easier and usually faster queries. Might be more
work up front, but down the road writing queries that don't have to mask off
bits (and remember what each one means) is a lot easier.
 
X

xanthviper

Actually, it's funny you say that. That was my original thinking when I
designed the database. However, I left out of this whole thread about
10 other flags that would have to be set for each of our "documents" if
you will.

We have a lot of switches that correspond to our document on who has
access to what, what system has access, etc. We would have ended up
with multiple bit fields indicating for true fals comparisions. Since
we are doing a redesign of our old system that had this, and we brought
in a few dba's, they suggested this would be the correct approach for
what it is we need to do. Thank you though, I do appreciate the
suggestion.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top