Sign in to follow this  

[.net] Bitwise check - best way?

This topic is 3591 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm looking for the best way to check for a bit within a value. My current operation does the following, but I think it's cumbersome maybe:

//here's the enum with the bitwise values:

    /// <summary>
    /// This enumerates the various data types that can be modified within the buffers of the VertexEngine system.
    /// </summary>
    public enum DataType
    {
        /// <summary>
        /// Indicates None.
        /// </summary>
        None=0,
        /// <summary>
        /// Indicates Vertex data.
        /// </summary>
        Vertex=1,
        /// <summary>
        /// Indicates Index data.
        /// </summary>
        Index = 2,
        /// <summary>
        /// Indicates UV data.
        /// </summary>
        UV = 4
    }

//here's the check I do to see if a member (this.bufferDataChanged) holds one of the enums:

    if ((this.bufferDataChanged & DataType.Vertex) == DataType.Vertex) {do this...}


Thanks for any help, Devin

Share this post


Link to post
Share on other sites
That's pretty much the standard way to check for a bit in a bitfield. If you're looking for that bit and that bit only, then yes, you'll need to be using the == operator. A bitfield is used to indicate a range of options which may exist in any combination. If you only check for one sole condition (a single bit begin set), then you don't want a bitfield, you want a variable holding the enum value.

Share this post


Link to post
Share on other sites
Quote:
If you only check for one sole condition (a single bit begin set), then you don't want a bitfield, you want a variable holding the enum value.


Not sure what you mean, can you explain more please?

Quote:
What's wrong with that? That's the way I do it.


I guess I'm looking for something more C# like :) ya know like:


if (this.bufferDataChanged 'contains' DataType.Vertex) {do this...}



Seems like that would be a pretty common use for us programmers. I guess I thought there was something already there that I was missing. Perhaps not.

Share this post


Link to post
Share on other sites
> Not sure what you mean, can you explain more please?

I assume he means, you don't really need to use bits if only one of the bits can be set a given time, and not multiple bits, so you probably would be better using enumeration or something.

Share this post


Link to post
Share on other sites
Quote:
Original post by KulSeran
you really only need to write
if (this.bufferDataChanged & DataType.Vertex)
the == DataType.Vertex is redundant


Maybe in some other languages, but in C# that statement will return a DataType not a bool, and the compiler will complain.

Share this post


Link to post
Share on other sites
Quote:
Maybe in some other languages, but in C# that statement will return a DataType not a bool, and the compiler will complain.


That's what I thought but wasn't sure. I haven't tried it yet, still just coding, not compiling yet.

Quote:
I assume he means, you don't really need to use bits if only one of the bits can be set a given time, and not multiple bits, so you probably would be better using enumeration or something.


Yea it is a bitwise enumeration:

public enum DataType
{
None=0,
Vertex=1,
Index = 2,
UV = 4,
XYZ = 8,
Norm = 16
}

Setting the values of each enum member to the corresponding bit placement. Then I can mix enum members together as I will. Because I do in fact need to mix two or more enum members together at times.

Share this post


Link to post
Share on other sites
You are only missing one nice feature of .Net, the FlagsAttribute

[Flags]
public enum DataType
{
None=0,
Vertex=1,
Index = 2,
UV = 4,
XYZ = 8,
Norm = 16
}




If you have something like

DataType dt = DataType.Vertex | DataType.Index;

If you are not using the FlagsAttribute, when you check the value while debugging or when you use the ToString you will see the value 3, as expected, but with FlagsAttribute you will see the value "Vertex | Index" while debugging and ToString will return "Vertex, Index" instead of 3, so you don't have to figure out which bits are set while debugging.

Share this post


Link to post
Share on other sites
If you just want to reduce the amount of typing you do, you can use != 0 rather than == DataType.Vertex. Or for the evil operator overloading crowd:

class Contains {
Contains(DataType d) { v = d; }
DataType v;
public static bool operator &(Contains c, DataType d) {
return (c.v & d) != 0;
}
public static explicit operator Contains(DataType d) {
return new Contains(d);
}
}

if ((Contains)this.bufferDataChanged & DataType.Vertex) {do this...}

Share this post


Link to post
Share on other sites
Quote:
You are only missing one nice feature of .Net, the FlagsAttribute


Super awesome! Didn't know that. I will use that from now on.

Hey, along that subject, what's the difference between [Flags] and [Flags()]? Is there? Or is it just extra typing?

SiCrane,

Holy Crap, how did you figure that out? That's pretty interesting and smart. Thanks. I wonder if a universal one can be made for various different enums? Or if we can somehow custom add our own operator to Visual Studio 2005-2008? Perhaps thru the SDK? Hmmm...

-Devin

Share this post


Link to post
Share on other sites
If you really want one for all Enums:

class Contains {
Contains(Int64 d) { v = d; }
Int64 v;
public static bool operator &(Contains c, Enum d) {
return (c.v & Convert.ToInt64(d)) != 0;
}
public static explicit operator Contains(Enum d) {
return new Contains(Convert.ToInt64(d));
}
}

It's still evil, however.

Share this post


Link to post
Share on other sites
Cool, I also put in a feature request for something to this effect with a keyword.

[edit]

Quote:
It's still evil, however


Ya I would tend to think that is a bit around the corner and down the road and across the bridge thru some towns, and so on :) But still you figured it out which gives merit.

[Edited by - devronious on February 10, 2008 8:25:45 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
If you really want one for all Enums:

class Contains {
Contains(Int64 d) { v = d; }
Int64 v;
public static bool operator &(Contains c, Enum d) {
return (c.v & Convert.ToInt64(d)) != 0;
}
public static explicit operator Contains(Enum d) {
return new Contains(Convert.ToInt64(d));
}
}

It's still evil, however.


You might go the extra mile and make a C# 3.0 extension method on the Enum base class itself. I don't have my tools installed on this machine yet (building a new computer) but it seems like you should be able to make something less "evil" that way.

Share this post


Link to post
Share on other sites
I'm not really familiar with C# 3 right now. Could you give an example when you're set up?

Quote:

Cool, I also put in a feature request for something to this effect with a keyword.

Though if you really want something that looks like a keyword:

public struct Proxy {
internal long v;

public Proxy(long val) {
v = val;
}

public static bool operator >(Proxy p, Enum e) {
return (p.v & Convert.ToInt64(e)) != 0;
}

public static bool operator <(Proxy p, Enum e) {
return (p.v & Convert.ToInt64(e)) != 0;
}
}

struct C {
public static Proxy operator <(Enum e, C c) {
return new Proxy(Convert.ToInt64(e));
}
public static Proxy operator >(Enum e, C c) {
return new Proxy(Convert.ToInt64(e));
}

static C contains = new C();
}

if (this.bufferDataChanged <C.contains> DataType.Vertex) {do this...}
// or
C contains = new C();
if (this.bufferDataChanged <contains> DataType.Vertex) {do this...}

As you may imagine, still evil.

Share this post


Link to post
Share on other sites
A C#3 example could be something like this:
public static class EnumContains {
public static bool Contains(this Enum e, Enum bit) {
return (Convert.ToInt32(e) & Convert.ToInt32(bit)) != 0;
}
}


You could then use it like this:
class Program {

[Flags()]
public enum DataType {
None = 0,
Vertex = 1,
Index = 2,
UV = 4,
XYZ = 8,
Norm = 16
}

static void Main(string[] args) {

var Test = DataType.UV | DataType.Norm;

Console.WriteLine("Test = {0}", Test);

foreach (DataType Bit in Enum.GetValues(typeof(DataType))) {
Console.WriteLine("Test.Contains({0})\t={1}", Bit, Test.Contains(Bit));
}

}
}

Share this post


Link to post
Share on other sites

This topic is 3591 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this