I don't know why I get 6 as a result when I insert a blank media in my burner. To my understanding there is no 6 in the states of the enumeration of IMAPI_FORMAT2_DATA_MEDIA_STATE.
Here is a link that contain this states and the example that I am based on : MSDN:Checking Media Support.
var state = dataWriter.CurrentMediaStatus;
Debug.WriteLine((int)state); // outputs 6
It is a combination of both of them, basically a bitwise operation is calculated on the two (or more values).
When you make an enum with the attribute Flags then you can do Bitwise operations on it, even though it should work without the attribute
IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK
IMAPI_FORMAT2_DATA_MEDIA_STATE_APPENDABLE
The value of IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK with an 'OR' operation with IMAPI_FORMAT2_DATA_MEDIA_STATE_APPENDABLE will give 6
in C# it would be value = 2 | 4;
To go further if you want to test if the value contains a certain Option you can go ahead and do something like this
if ((value & IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK) == IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK)
{
//IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK is contained
}
You can read more about Bitwise operations here
It's equivalent to a flaggable enum. 6 is 4 + 2, so the state is both
IMAPI_FORMAT2_DATA_MEDIA_STATE_BLANK
IMAPI_FORMAT2_DATA_MEDIA_STATE_APPENDABLE
Related
This question already has answers here:
Do .net FlagsAttribute enums need to be manually valued?
(2 answers)
Any trick to defining an enum as flags/powers of 2 without eventually needing a calculator?
(6 answers)
Closed 2 years ago.
By default, if no Enum value are assigned, they are automatically assigned by the compiler with a zero-based index:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
Assigning binary values to the Enum members allows doing bitwise operations, and they can be assigned by sequencing values in orders of magnitude of 2:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
or, more conveniently, make bitwise shifts:
[Flags]
public enum MyColors
{
Yellow = 0,
Green = 0 << 0,
Red = 0 << 1,
Blue = 0 << 2
}
But what if I now want to add Orange to this list between Yellow and Green, while keeping the value numbering nice and consistent? This is the intended result:
[Flags]
public enum MyColors
{
Yellow = 0,
Orange = 0 << 0
Green = 0 << 1,
Red = 0 << 2,
Blue = 0 << 3
}
As you can see, I had to manually edit the shift operations after Orange to keep the numbering nice and consistent. This can quickly become cumbersome with very large Enums. This is not Microsoft Word where you can insert a new item into a numbered list and have the list numbering update automatically after the inserted item. But this kind of feature would be very nice to have.
The problem arises from having to specify the Enum values to binary sequence manually, because by default the Enum members are numbered in decimal.
So, my question is, is it possible to change this default compiler behavior to assign values to Enum members using binary sequence logic, instead of the default decimal one? I am coding with Visual Studio in case that matters.
Disclaimer: I am fully aware that the order of items in Enum doesn't really matter in most cases, nor does the assignment of the member values, meaning I could insert Orange at the bottom and skip having to edit the rest of the member values, or insert Orange where I want, and have a bit messed up numbering sequence. But in certain cases it kind of matters where the newly inserted member is (for example, when printing the Enum member names through reflection), and having the value numbering without any order makes it difficult to determining the value in sequence for a new member. That is why I want to skip having to specify these binary values altogether, and have compiler assign them automatically.
Maybe this extensions for visual studio can help you. https://marketplace.visualstudio.com/items?itemName=VictorCherniavsky.EnumComposerVSIX
Based on documentation it generate enum using specified database query. So you can manage yours flags in dedicated database table and then regenerate enum before build.
Another option is set flag values as binary literals
[Flags]
public enum MyColors
{
None = 0b000000,
Green = 0b000001,
Red = 0b000010,
Blue = 0b000100,
Yellow = 0b001000,
}
For checking for duplicates I suggests using some analyzer for example Roslynator.
The answer is simple: No, it's not possible to change the behaviour of the C# compiler in this way
I am after some quick code to help with my logic on bitwise code (my first time doing it)
Basically I have 3 properties each with an ID of 1,2,4
int A = 1
int B = 2
int C = 4
Lets say A and C are checked, this will equal 5 and this value will be saved into the database. Good.
Now I need to work out on the way back what was checked with that value.
So in the example, the value is 5, so how will I know with bitwise logic what properties were checked?
So I am not asking for you to do my work, knowing what I do,
int i = A & C;
// if i == 5, then we know it was A and C checked
But do you need to do that for each possibility?
Thanks in Advance
You can simply check for these conditions:
i & A != 0 // true if A is set in i
i & B != 0 // true if B is set in i
Having said that, bitfields are inappropriate in lots of situations. Especially when you store the resulting value into a database it is usually better to just define some more columns storing each flag.
I have wrote enum:
[Flags]
public enum BundleOS {
Win32 = 0,
Win64 = 1,
Mac = 2
}
I need parse it from string, and write to string. Sample of string: "Win32|Win64".
Next code returns invalid result:
BundleOS os;
Boolean result = TryParse<BundleOS>("Win32|Win64", out os);
In result variable I got the false value. But I need true, and os value must to have the BundleOS.Win32|BundleOS.Win64 value.
If I do such operation:
String x = (BundleOS.Win32|BundleOS.Win64).ToString();
I need get such value: "Win32|Win64", but I get "Win64".
Is exists a simple solution of these problems?
Your problem is that your performing a bitwise operation and Win32 equals 0.
So Win64 OR Win32 is actually Win64 OR 0 which returns Win64.
You can set your enum like this:
[Flags]
public enum BundleOS
{
Win32 = 1,
Win64 = 2,
Mac = 4
}
On a side note:
I'll also point out a very good question that was asked earlier this week on how to define flag enums.
In addition to the answer given by #Blachshma regarding your particular flags, if you want to take the string form of "Win32|Win64" and turn it into an actual instance of your enum, you've got a bit more work cut out.
First you'll simply need to split() the string by the '"|"' in order to get the individual values.
Then you can use Enum.GetNames() and Enum.GetValues() to get a list of the names and values for elements in your original enum. You can then loop through the split components, and find the matching entry (and its value) from your original enum.
Try this to parse your flags string. I havn't tested but it should get you started:
BundleOS flags = "Win32|Win64"
.Split('|')
.Select(s => (BundleOS)Enum.Parse(typeof(BundleOs), s))
.Aggregate((f, i) => f|i);
In addition to Blachshma's answer, the MSDN documentation for the FlagsAttribute actually explains very succinctly in the "Guidelines for FlagsAttribute and Enum" section:
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.
Use None as the name of the flag enumerated constant whose value is
zero. You cannot use the None enumerated constant in a bitwise AND
operation to test for a flag because the result is always zero.
However, you can perform a logical, not a bitwise, comparison between
the numeric value and the None enumerated constant to determine
whether any bits in the numeric value are set.
I haven't really used bitwise enums before, and I just want to make sure my testing is correct. I am most interested in testing for the values None and All. We receive data from a webservice that utilises this enum to categorise certain pieces of the data. Given that, I am assuming that nether None nor All would ever be combined with any other value.
Given the following bitwise enum definition;
[System.FlagsAttribute()]
public enum TrainingComponentTypes : int
{
None = 0,
AccreditedCourse = 1,
Qualification = 2,
Unit = 4,
SkillSet = 8,
UnitContextualisation = 16,
TrainingPackage = 32,
AccreditedCourseModule = 64,
All = 127,
}
I read the following quote on this MSDN site about FlagAttributes;
Use None as the name of the flag
enumerated constant whose value is
zero. You cannot use the None
enumerated constant in a bitwise AND
operation to test for a flag because
the result is always zero. However,
you can perform a logical, not a
bitwise, comparison between the
numeric value and the None enumerated
constant to determine whether any bits
in the numeric value are set.
Does a logical comparison in this instance refer to a normal equality test for enums?
For example;
TrainingComponentTypes tct = TrainingComponentTypes.None;
if (tct == TrainingComponentTypes.None)
{ ... }
For a bitwise comparison, I am performing the following;
TrainingComponentTypes tct = TrainingComponentTypes.AccreditedCourse | TrainingComponentTypes.Qualification | TrainingComponentTypes.TrainingPackage;
Assert.IsTrue((tct & TrainingComponentTypes.AccreditedCourse) == TrainingComponentTypes.AccreditedCourse, "Expected AccreditedCourse as part the enum");
Assert.IsFalse((tct & TrainingComponentTypes.SkillSet) == TrainingComponentTypes.SkillSet, "Found unexpected SkillSet as part the enum");
Lastly, when testing for all, I have tried both a logical, and bitwise comparison, and they both return the same. Should I be using one over the other here? For example;
TrainingComponentTypes tct = TrainingComponentTypes.All;
Assert.IsTrue((tct & TrainingComponentTypes.All) == TrainingComponentTypes.All, "Expected All as part the enum");
Assert.IsTrue((tct) == TrainingComponentTypes.All, "Expected All as part the enum");
// The follow also pass the assertion for a value of All
Assert.IsTrue((tct & TrainingComponentTypes.Qualification) == TrainingComponentTypes.Qualification, "Expected Qualification as part the enum");
Assert.IsTrue((tct & TrainingComponentTypes.TrainingPackage) == TrainingComponentTypes.TrainingPackage, "Expected TrainingPackage as part the enum");
So in summary, I'd like to know the following about Bitwise enums;
Is my understanding of a logical
comparison correct given my example
above?
Is the way I am performing
a bitwise comparison correct?
What is the right way to handle the "All"
value (bitwise or logical). I am not sure if we'd ever receive a value where All was combined with other TrainingComponentTypes. I can't see why we would, but then, you never know?
Am I right in assuming that switch
statements basically shouldn't be
used for bitwise enums (given none
is appears to be a special case and
requires a logical comparison)?
Thanks,
Chris
Short answer: Yes :)
Longer:
1) All operations are performed on the integer value of the flags variable, so you can think about them in terms of this.
2) Yes.
3) Either works. However, it's worth noting that if someone shoves an invalid value into a variable then the == TrainingComponentTypes.All version will fail. For example:
var badValue = (TrainingComponentTypes)128 | TrainingComponentTypes.All;
// now badValue != TrainingComponentTypes.All
// but (badValue & TrainingComponentTypes.All) == TrainingComponentTypes.All
For this part:
I am not sure if we'd ever receive a value where All was combined with other TrainingComponentTypes.
I'm not sure you fully understand how the enum works under the covers.
The value of All is:
127 = 1111111 (binary)
The other values are:
AccreditedCourse = 0000001
Qualification = 0000010
Unit = 0000100
SkillSet = 0001000
UnitContextualisation = 0010000
TrainingPackage = 0100000
AccreditedCourseModule = 1000000
As you can see, All is simply the bitwise | of all these values together. You can't combine any other TraningComponentTypes with All, because All already includes them! Also, if you combine them all together with | yourself it's exactly the same as using All directly (so, All is simply a convenience when you define it inside an enum).
4) You could use it to check for None or All but not for other values.
It's worth noting that there is a convenience method on Enum that will do these checks for you: Enum.HasFlag.
Is my understanding of a logical comparison correct given my example above?
Yes, logical in this context means the equality and inequality operators.
Is the way I am performing a bitwise comparison correct?
Yes, but there is an easier way: Enum.HasFlag. For example:
tct.HasFlag(TrainingComponentTypes.Qualification)
instead of:
(tct & TrainingComponentTypes.Qualification) == TrainingComponentTypes.Qualification
What is the right way to handle the "All" value (bitwise or logical). I am not sure if we'd ever receive a value where All was combined with other TrainingComponentTypes. I can't see why we would, but then, you never know?
I think it is better to define All in the enum itself as the bitwise OR of all its parts. But you'll see people do it both ways.
Am I right in assuming that switch statements basically shouldn't be used for bitwise enums (given none is appears to be a special case and requires a logical comparison)?
No, not at all. Feel free to use them is switch statements. The case values must be constants but they can be expressions and are tested for equality. The compiler will tell you if you do something silly like try to use the same case value twice.
Yes.
Yes
Both logical and bitwise could be used. Usage depends on whether all is all bits set or just the bitwise OR of all the values you've defined.
Yes, but not because of None. A switch compares a single value, whereas a bit field can obviously have multiple values.
As others have noted Enum contains HasFlag().
1 and 2 - yes, however there is a way to make it a little easier to read:
TrainingComponentTypes tct = TrainingComponentTypes.AccreditedCourse | TrainingComponentTypes.Qualification;
Assert.IsTrue(tct.HasFlag(TrainingComponentTypes.AccreditedCourse), "Expected AccreditedCourse as part the enum");
3 - I am not sure if you need All value at all. I would remove it.
4 - Yes, switch statement usually doesn't make sense for Flags enumerations.
"3.What is the right way to handle the "All" value (bitwise or logical). I am not sure if we'd ever receive a value where All was combined with other TrainingComponentTypes. I can't see why we would, but "
It seems you misunderstand how the bitwise enum values work. 'All' is always combined with other values, in fact it is the combination of all the values. Looking at the binary values for your enum:
None = 0,
AccreditedCourse = 1,
Qualification = 10,
Unit = 100,
SkillSet = 1000,
UnitContextualisation = 10000,
TrainingPackage = 100000,
AccreditedCourseModule = 1000000,
All = 1111111
does that help your understanding?
1&2 look fine
3.
All as you have it defined can't be combined with anything without losing data. If "all" is a real value that you expect to receive from the server you should probably change it to 128.
otherwise it is a convenience value that you can use to test if any value is set... you shouldn't need this unless your flag values are sent as binary data and packed in a byte that may contain other data.
4.
Switch statements could be used but will not work well if/when you have values that have more than one flag, if there are small subsets of valid flag combinations they can still be useful.
In model
as_enum :shifts, { day_shift: 0,
evening_shift: 1,
night_shift: 2,
}, accessor: :bitwise
And in Views
Model.enum_collection(:shifts)
I'm browsing an open source .NET twain wrapper and saw this:
[Flags]
internal enum TwDG : short
{ // DG_.....
Control = 0x0001,
Image = 0x0002,
Audio = 0x0004
}
What exactly does that 'Flag' decorator mean? (Is it called a 'decorator'?)
Also, what does the short mean at the end of the enum declaration?
Thanks!
The Flags Attribute is used to allow and decorate the enumeration for bitwise math operations on enum values.
Doing this allows you to add them together, or other operation items.
The Short part defines it as a Short rather than an integer, detail on this is also in the linked URL
It's an attribute. Although others have said that it is necessary so that you can perform bit flipping operations with the enum, this is not true. You can do this with enums without this attribute.
If you have applied the attribute, you get a different ToString() output on the enum which will pretty-print the combined members of a enum value, e.g. "Blue | Red | Orange", instead of "7".
The "short" keyword means that the type for the enum members will be a 16-bit signed integer.
It means that you give a hint, that this enum will be used for "bitwise or" operations
var flags = TwDG.Control | TwDG. Image;
Console.WriteLine(flags.HasFlag(TwDG.Image)); // true
Console.WriteLine(flags.HasFlag(TwDG.Control)); // true
Console.WriteLine(flags.HasFlag(TwDG.Audio)); // false
More info FlagAttribute (Enum.HasFlag was added in Framework 4.0)
Short is saying, that back-type for this enum is not int (which is default option for enums), but short. Also you can specify long, ushort, or any other integer built-in type.
short is another keyword for System.Int16, a two-byte integer ranging from -32,768 to 32,767. By default, an enum's base type is int; in this case, they're attempting to use a smaller data type to store the enumerator values.
Its the flag attribute, you can read up on it here:
http://msdn.microsoft.com/en-us/library/cc138362.aspx
Lets you treat a set of enums a bit flag set.
the short means that the enum is using short instead of an int as its base type.
as for the flags
http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx
This makes an enumeration a bit-flag.
It means you can combine individual values together.
Like:
TwDG value = TwDG.Control | TwDG.Image | TwDG.Audio;
Which would give it a value of 7.
Individual enumeration values usually have a value of 2^n. But can as well be combined like:
[Flags]
public enum Sides
{
Left = 1,
Right = 2,
Up = 4,
Down = 8,
LeftAndRight = 3,
UpAndDown = 12,
AllSides = 15
}
As for [Flag] - you should look here link text
Short - data time, which used to store enum values.
Flags is an attribute; specifically, System.FlagsAttribute.
It means that the compiler lets you use values of type TwDG as a bit-field, i.e., store as many of them as you want in one value like this:
var control = TwDG.Control;
var allTogether = TwDG.Control | TwDG.Image | TwDG.Audio;
Typically, this is done when some code needs to take different (or optional) actions depending on if one of these flags is set. For example, let's say we want to describe the contents of a video file, which might contain audio and picture. You could write:
var imageAndAudio = TwDG.Image | TwDG.Audio;
var muteImage = TwDG.Image;
Then, if you wanted to check if the file contains an audio track, you would "pick out" the Audio flag like this:
var hasAudio = (myValue & TwDG.Audio) != (TwDG) 0;
I've heard them called decorators before (and it is acceptable to label them as such in the community) but for arguments sake and strictly speaking; it is an attribute. It is used to "mark" the enum as a bit flag type.
Here's the MSDN Reference.