How to get values of combined bitwise - c#

I have types that have a bitwise value [1,2,4,8,16,32] that are selected from checkboxes, when saving to the database i combine the selected values and get a value of 42 for instance. How can i calculate which values were selected from the combined value, on an edit screen i want to recheck the values that were selected.

To check whether e.g. 8 is contained in your combined value, you can use the bitwise and operator like this:
int combinedValue = 42;
int bitwiseValue = 8;
bool isBitwiseValueChecked = (combinedValue & bitwiseValue) == bitwiseValue;

Use an enum to model the flags:
public static void Main()
{
Console.WriteLine((MyFlags)1); // Foo
Console.WriteLine((MyFlags)7); // Foo, Bar, Baz
Console.WriteLine((int)(MyFlags.Foo | MyFlags.Bar)); // 3
}
[Flags]
enum MyFlags
{
Foo = 1,
Bar = 2,
Baz = 4
}
Then, to list all members, see List all bit names from a flag Enum

Related

C# List binary or items together into one bitmask result

I have a list of bit flags in c# in a list. I would like to binary or them together to generate a bitmask.
For example a modifierKey enum that is treated as a bit field with the Flags attribute like so:
[Flags]
public enum ModifierKeys : uint
{
Alt = 1,
Control = 2,
Shift = 4,
Win = 8
}
I know I can do this with a for loop and just bitwise or the values together as uints and then cast back to the enum type. My current working method looks like so:
public ModifierKeys ComputeMask(List<ModifierKeys> keys)
{
uint value = 0;
foreach(var item in keys)
{
value |= (uint)item;
}
return (ModifierKeys)value;
}
To my question - Can I do this be done with a single LINQ query or some other extension I am missing?
Try this:
uint value = keys.Aggregate<ModifierKeys, uint>(0, (current, item) => current | (uint)item);

Do enums need an index?

I have a number of enums that contain long lists that do change from time to time
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}
When they change, I need to renumber the index as invariably new options are placed inbetween existing options.
The question is, if I remove the index, will the enum always honour the order from top to bottom?
public MyEnumType MyEnum
{
None,
Option1,
Option2,
etc..
}
Thanks in advance.
Yes they will.
You can also specify just the first element if you want to make sure that values start at some specific value:
public MyEnumType MyEnum
{
None = 1,
Option1, // -> 2
Option2, // -> 3
}
For other details, check the docs.
Note that in most scenarios, your code should not care about the exact numeric values.
Situations when you do care are e.g. if you declare an enum which is an alias for an external type (e.g interop) so you need to ensure that values are the same. Another scenario is when the enumeration represents binary flags, then you want something like:
[Flags]
public MyEnumType MyEnum
{
None = 1,
Option1 = 2,
Option2 = 4
}
Simplest answer would be "Yes"... they will always honor the order.
So you no need to put index number.
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionZ
}
this will always same as -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionZ = 26
}
If you introduce new enum type in between like -
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionO
OptionNew
OptionP
...
...
OptionZ
}
Then above will be equivalent to -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionO = 15
OptionNew = 16
OptionP = 17
...
...
OptionZ = 27
}
Yes they honour the order, starting from the default value for int, which is zero.
If you are regularly renumbering things then it is better to explicitly assign values to the enum members, and then re-number the items when the underlying list that it is based on changes.
If you use explicit numbering then you can also insert new items into the list between existing items at any time, although you do need to be careful that you don't assign two items to the same value (which is totally legal in C#, but may produce errors if you didn't intend it).
From the C# language specification 1.10 Enums:
... When an enum member declaration does not explicitly specify a value,
the member is given the value zero (if it is the first member in the
enum type) or the value of the textually preceding enum member plus
one.
So the same as your explicit declaration here:
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}
By default they will count up from zero in the order they are declared.
If you define one explicitly, then the subsequent values continue counting up, using the explicit value as a seed.

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

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.

C# Copying Enumeration from one object to another

I have two very similar but not identical C# objects. I am copying the values from one class to another.
Each class has some properties that expose an enumeration type. The inside of the enumerations are the same but the names are different e.g.
public enum EnumA
{
A,
B
}
public EnumA EnumAProperty
{
get{ return enumA;}
}
public enum EnumB
{
A,
B
}
public EnumB EnumBProperty
{
get{ return enumB;}
}
I want to assign the value returned from EnumBProperty to EnumAProperty is this possible?
You can do via casting but I would not recommend it as it is fragile — if any of the enum members are reordered or new items added the result may not be what you expect.
EnumAProperty = (EnumA) EnumBProperty;
Even worse with the casting is if you have items in your source enum with no equivalent in the destination — below there are more colours than shapes:
enum Color { Red = 0, Yellow = 1, Blue = 2 };
enum Shape ( Square = 0, Triangle = 1 };
Color color = Color.Red;
Shape shape = (Shape) color;
shape could end up with the value 2 even though this value is not defined.
Instead, I'd suggest you use a switch statement to map:
EnumAProperty = ConvertToA(EnumBProperty);
...
private static EnumA ConvertToA(EnumBProperty b)
{
switch (b)
{
case EnumB.Flannel: return EnumA.HandTowel;
case EnemB.Vest: return EnumA.UnderShirt;
...
default: throw new ArgumentOutOfRangeException("b");
}
}
Each enum member has a corresponding integer value.
By default, these values are assigned in ascending order, starting with 0.
If the order of the items in the enums (and thus their numeric values) are the same, you can just cast the numeric value to EnumB to get the EnumB member with the same value:
EnumBProperty = (EnumB)(int)EnumAProperty;
If not, you need to re-parse it:
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());
As long as both enum's of different types you can'not assign it directly.
You can define integer offset for an items so you can assign values through the integer value
public enum EnumA
{
A = 0,
B = 1
}
public enum EnumB
{
A = 0,
B = 1
}
EnumBPropertry = (int)EnumAProperty
You could either cast it to an integer or convert it to a string and then do an Enum.Parse on it.
Try the following:
EnumAProperty = (EnumA)Enum.Parse(typeof(EnumA), EnumBProperty.ToString);
EnumBProperty = (EnumB)Enum.Parse(typeof(EnumB), EnumAProperty.ToString());

Categories

Resources