Bitwise OR Combination - c#

This is one of the most used Regex functions
Regex.IsMatch("Test text for regex test.", "(test)",
RegexOptions.IgnoreCase | RegexOptions.Multiline);
Can you explain how Regex.IsMatch method works ?
I mean how it handles bitwise OR RegexOptions parameters ?
How it defines method parameters ?
Thanks for replies !

RegexOptions is an enumeration with the [Flags] attribute applied to it. This allows bitwise operations to be applied to the various values.
You can also do something similar:
[Flags]
enum MyOptions {
UpperCase = 1,
Reverse = 2,
Trim = 4
}
public static void DoTransform(MyOptions options) {
if ((options & MyOptions.UpperCase) == MyOptions.UpperCase) {
/* Do Upper case transform */
}
if ((options & MyOptions.Reverse) == MyOptions.Reverse) {
/* Do Reverse transform */
}
/* etc, ... */
}
DoTransform(MyOptions.UpperCase | MyOptions.Reverse);
I've just done a bit more digging based on Frank's comment and he is correct that with or without the [Flags] attribute, the code above will compile and run.
There have been other comments in regard to what the [Flags] attribute does not do but other than "it affects the ToString() result" no one seems to know or wants to explain what it does do. In code I write, I adorn enumerations that I intend to use as bitfields with the [Flags] attribute, so in that case it is at least somewhat self-documenting. Otherwise, I'm at a loss.

RegexOptions is an enumeration, meaning that internally, it's represented as an integer. The values of it look something like this:
// note the powers of 2
enum RegexOptions {
IgnoreCase = 1, MultiLine = 2,
SomeOtherOption = 4, YetAnotherThing = 8 }
The values are designed so that if you express them in binary, each one has a single bit on.
Because of this, if you take the bitwise OR of two values and end up with a result, you can figure out if one of the values is set (e.g. IgnoreCase) by evaluating (result AND IgnoreCase).

Related

Unexpected result in Enum.HasFlag

I recently encountered an error in my code where I was attempting to "dismantle" an enum flag into an array of its constituent values, but unexpected results would sometimes be returned.
Long story short, certain integer types assigned to my values appear to cause some behaviour that is unexpected (well, to me at least). I boiled down the issue into the following unit test:
public enum TestEnum
{
ITEM1 = 30104,
ITEM2 = 30201,
}
[TestClass]
public class EnumFlagTest
{
[TestMethod]
public void SanityCheck()
{
var flag2 = TestEnum.ITEM2;
Assert.IsFalse(flag2.HasFlag(TestEnum.ITEM1));
}
}
I did not expect flag2 to report that it "has the flag" of ITEM1, as I do not believe that it does.
I guess that it has something to do with the Int32 values I've assigned to the items, but please could someone explain what's going on?? - Why does this test fail?
Basically, you shouldn't use HasFlag for a non flags-based enum... and a flags-based enum should use a separate bit for each flag.
The problem is indeed because of the values. Writing this in binary, you've got:
public enum TestEnum
{
ITEM1 = 0b111010110011000,
ITEM2 = 0b111010111111001
}
Note how every bit that's set in ITEM1 is also set in ITEM2 - and that's what's checked by HasFlag. From the documentation:
Returns:
true if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, false.
That is true for TestEnum.ITEM2.HasFlag(TestEnum.Item1), hence it returns true.
The HasFlag method is a bitwise check and the bits of ITEM1 match up with ITEM2:
Note that ITEM2 contains all the same 1s that ITEM1 has:
ITEM1: 111010110011000
ITEM2: 111010111111001
It looks like you are wanting to use "Bit flags" - a collection of boolean values that are easy to merge.
To do that, each flag needs one bit set and the bit needs to be in a unique location.
But it is valid to combine flags to cover common groupings.
One technique I learned here on StackOverflow is to set the first flag and then bit-shift for the rest of the flags. Something like this:
[Flags]
enum color {
none = 0,
red = 1, // 0b0001
yellow = red << 1, // 0b0010
blue = yellow << 1, // 0b0100
primaries = red | yellow | blue, // 0b0111
green = yellow | blue, // 0b0110
purple = red | blue, // 0b0101
orange = red | yellow // 0b0011
}
with this, you can
Assert.IsFalse(Color.green.HasFlag(color.red));
Assert.IsTrue(Color.primary.HasFlag(color.red));
I hope that clears things up for you!
Note, the code here is largely pseudo-code; there may be syntax errors. The concept is, however, sound.

Alternative to operand && (C#)

so I'm trying to make a code with &&. However, when I put that in, it said that I couldn't apply the operand to it.
In specific, it reads: Operator "&&" cannot be applied to operands of type 'Server.Enums.PokemonType' and 'Server.Enums.PokemonType'
However, I need to be able to link these two things so I can make the code be two PokemonTypes. So is there any alternative or work-around for not being able to use &&?
If you need it, this is my code:
case 225:
{
//Flying Press -- INCOMPLETE, needs Flying-type
setup.Move.Element = Enums.PokemonType.Fighting && setup.Move.Element = Enums.PokemonType.Flying;
if (setup.Defender.VolatileStatus.GetStatus("Minimize") != null)
{
setup.Multiplier *= 2;
setup.Move.Accuracy = -1;
}
}
break;
The system defined && operator only supports boolean operands. The & operator will work for enums (because it also works on all integer types, which the enums are based on). Of course, if you want an enum that represents the combination of two flag values then you'll want to OR them together (using |), not AND them together.
To add multiple values to a enum variable you need to declare the enum with [Flags] attribute.
So your enum would be:
[Flags]
public enum PokemonType
{
Fighting = 1 << 0,
Flying = 1 << 1,
Normal = 1 << 2,
Dragon = 1 << 3,
}
Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap
Then assign using Enums.PokemonType.Fighting | Enums.PokemonType.Flying so it is possible to track all values assigned to it later.

What is the behaviour of FlagsAttribute Enum in C#?

I have the following code:
namespace ConsoleApplication1
{
internal class Program
{
[FlagsAttribute]
private enum RenderType
{
DataUri = 0,
GZip = 1,
ContentPage = 2,
ViewPage = 4,
HomePage = 8
}
private static void Main()
{
// 4.
// Set a new enum in three statements.
RenderType type2 = RenderType.ViewPage;
// 5.
// See if the enum contains this flag.
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.DataUri) == RenderType.DataUri)
{
Console.WriteLine("DataUri");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
}
}
Whenever I run this code, it gives me an output of:
ViewPage
DataUri
I want output of just ViewPage as I am giving the value to my enum ViewPage.
Can anyone help me here? Why is this? Is there anything wrong with my Enum declaration or code?
You have declared DataUri = 0 so
(type2 & RenderType.DataUri) == RenderType.DataUri
will always evaluate to true.
Start your valid enum values at 1.
Any number bitwise anded with zero is zero. Start the enum with one and increase by powers of two. Also, a better understanding of binary numbers and bitwise operators will help
DataUri is 0: so x & DataUri is always zero!
Try this:
if(type2 != RenderType.DataUri) {
if ((type2 & RenderType.ViewPage) == RenderType.ViewPage)
{
Console.WriteLine("ViewPage");
}
if ((type2 & RenderType.GZip) == RenderType.GZip)
{
Console.WriteLine("GZip");
}
}
When using Bitmasks the value 0 usually indicates a NONE-Flag. So you should start to count from 1 to 2^n, which is a better practise IMHO:
[FlagsAttribute]
private enum RenderType
{
None = 0,
DataUri = 1,
GZip = 2,
ContentPage = 4,
ViewPage = 8,
HomePage = 16
}
Because x & 0 always equals zero.
Don't specify 0 (zero) as a possible value for a [Flags] enum. Remember that a [Flags] enum is a bit field, and a value of zero doesn't really map into any of the fields, so it will always return true.
From the Framework Design Guidelines by Krzysztof Cwalina:
Avoid using flag enum values normal members that are negative or zero.
Negative values produce unexpected/confusing results in bitwise operations. An enum value of zero creates problems with and operations, etc:
The reason is that RenderType.DataUri has the value 0.
What your code does is to inspect the bitwise configuration of the type2 enum variable by performing a bitwise and operation between type2 and the enum member it's testing for.
In your example, type2 has the value 4, which is 0100 in binary (up to the 4 bits that your enum requires). When you test for RenderType.GZip (0001), it does the following calculation:
0100 & 0001 = 0000
Since 0000 != 0001, the RenderType.GZip bit is not set in type2. However, 0100 & 0000 is always 0000, so you'll always get true when checking for RenderType.DataUri.
Essentially, a Flags enum uses a different bit for each of its members, but since 0 doesn't represent a bit in an integer, it won't behave as expected.
As others have said you should start Flags enums at 1 due to how binary arithmetics work. I just want to add that you may want to use the HasFlag method (I believe new in .NET 4.0) to check the flags:
if(type2.HasFlag(RenderType.ViewPage))
{
...
}
http://msdn.microsoft.com/en-us/library/system.enum.hasflag.aspx

Bitwise subtraction

Given the enum:
[Flags]
enum foo
{
a = 1,
b = 2,
c = 4
}
then
foo example = a | b;
If I don't know if foo contains c, previously I have been writing the following
if (example & foo.c == foo.c)
example = example ^ foo.c;
Is there a way to do this without checking for the existance of foo.c in example?
As when it comes to additions, I can just do an OR, and if the enum value already exists in example then it doesnt matter.
I think you want:
example &= ~foo.c;
In other words, perform a bitwise "AND" mask with every bit set except the one for c.
EDIT: I should add an "except" to Unconstrained Melody at some point, so you could write:
example = example.Except(foo.c);
Let me know if this would be of interest to you, and I'll see what I can do over the weekend...
AND it with the complement of foo.c:
example = example & ~foo.c

Convert CSV from enum flags and vice versa

Consider the following enum:
[Flags]
public enum MyEnum
{
Option1 = 0,
Option2 = 1,
Option3 = 2,
Option4 = 4
}
Is there a way in which I can get the string equivalent (not the value) as a CSV string? Normally I can use the Enum.GetName function to convert a type to the string representation, however, if you use a combination this returns null.
So basically I would like to convert:
var options = MyEnum.Option1 | MyEnum.Option3;
into
"Option1, Option3"
Then I would like to be able to convert "Option1, Option3" back to MyEnum.Option1 | MyEnum.Option2.
Suggestions?
Well, aside from Option1 not making much sense in a flags enum, this just works by default using Enum.Parse and Enum.ToString().
Start with this:
var options = MyEnum.Option2 | MyEnum.Option3;
Console.WriteLine(options.ToString());
// Outputs: Option2, Option3
Then you can always do this:
var options2 = (MyEnum) Enum.Parse(typeof (MyEnum), "Option2, Option3");
Now try this:
Console.WriteLine((options2 & MyEnum.Option2) == MyEnum.Option2);
Console.WriteLine((options2 & MyEnum.Option4) == MyEnum.Option4);
// Outputs:
// true
// false
Which seems like it does exactly what you wanted (again, ignoring the fact that Option1 in your example will never occur)
docs: Enum.Parse
You could do a Enum.GetValues which gets an array of enum values. You can then loop through those values and test them against your Enum value, concatenating the string value for each one that matches. The other way around you can loop through the values using the Enum.GetName function to test if your string contains that values name and then rebuild the value.

Categories

Resources