Problems with Enum as Flags - c#

I have the following enum:
[Flags]
public enum Status { Nominal, Modified, DirOneOnly, DirTwoOnly, DirOneNewest, DirTwoNewest }
I am attempting to see whether the Modified bit has been set to true and have tried the following methods:
if(_stateFlags.HasFlag(Status.Modified))
{
//DoStuff
} //Found out why this doesn't work after reading docs.
and
if((_stateFlags & Status.Modified) == Status.Modified)
{
//DoStuff
}
The latter is the method that my further research led me to believe would work. However, when I do _stateFlags = Status.DirTwoOnly the above statement still seems to evaluate to true which is really puzzling me.
Am I doing something fundamentally wrong?

You have several answers to your question explaining what is wrong. I would suggest taking a different approach entirely.
Flags enums have a very 1990s feel to them; if you think they look like they're there for COM interop, and if you think COM enums look like they are for compatibility with bit-twiddling code from the 1970s, you're right.
I would not express this logic as an enum in new code. I would take the time to write a custom struct that clearly expresses my actual semantics.
struct Status
{
public static readonly Status None = default(Status);
private Status(int bits) { this.bits = bits; }
private int bits;
private const int NominalBitMask = 0b0001;
private const int ModifiedBitMask = 0b0010;
... etc ...
public bool IsNominal => (this.bits & NominalBitMask) != 0;
public Status WithNominal(bool f) =>
new Status(f ? (this.bits | NominalBitMask) : (this.bits & ~NominalBitMask));
... etc ...
And now you can use it like:
Status status = Status.None.WithNominal(true).WithModified(myFile.IsModified);
...
if (status.IsModified) ...
Is this more work up front? Sure, it's about twenty minutes more work up front. But you then never make any bit twiddling mistake ever again. You have a struct you can test independently of the logic that uses it. You have code that looks like what it means. You never have to worry about someone casting an integer to your enum type and having it full of nonsense. You can put custom logic in your type; suppose for example there are three-valued flags -- true, false or null, say -- those are hard to do in flags enums but you can add the logic easily in a custom type. And so on.

You need to define the enum constants as powers of two.
[Flags]
public enum Status
{
Nominal = 1,
Modified = 2,
DirOneOnly = 4,
DirTwoOnly = 8,
DirOneNewest = 16,
DirTwoNewest = 32
}
class Program
{
static void Main(string[] args)
{
Status s = new Status();
s |= Status.Modified;
if (s.HasFlag(Status.Modified))
{
Console.WriteLine("Modified!");
}
}
}

The code:
[Flags]
public enum Status { Nominal, Modified, DirOneOnly, DirTwoOnly, DirOneNewest, DirTwoNewest }
is equal to:
[Flags]
public enum Status
{
Nominal = 0, // in bits: ... 0000 0000
Modified = 1, // 0000 0001
DirOneOnly = 2, // 0000 0010
DirTwoOnly = 3, // 0000 0011 **common bit with Modified state **
DirOneNewest = 4,
DirTwoNewest = 5,
}
So as other people said, you need to use power of 2 for enum values.

Related

console.cs IsHandleRedirected oddity

MS' own console.cs has the following function, used by the IsInput/Output/ErrorRedirected APIs.
private static bool IsHandleRedirected(IntPtr ioHandle) {
// Need this to use GetFileType:
SafeFileHandle safeIOHandle = new SafeFileHandle(ioHandle, false);
// If handle is not to a character device, we must be redirected:
int fileType = Win32Native.GetFileType(safeIOHandle);
if ((fileType & Win32Native.FILE_TYPE_CHAR) != Win32Native.FILE_TYPE_CHAR) // <--- ??
return true;
// We are on a char device.
// If GetConsoleMode succeeds, we are NOT redirected.
int mode;
bool success = Win32Native.GetConsoleMode(ioHandle, out mode);
return !success;
}
I don't understand the logic on the line marked (by me) with // <--- ??. It would have made sense that if (fileType != Win32Native.FILE_TYPE_CHAR) return true;, but I don't follow why it's masked with & Win32Native.FILE_TYPE_CHAR before comparing.
To make it more confusing, the constant FILE_TYPE_CHAR is the single bit 0x0002 which is also shared by FILE_TYPE_PIPE = 0x0003, so the if statement in question will not return true; if the file handle refers to a pipe (maybe relying on GetConsoleMode to fail afterwards??).
Any insight into why that code was written the way it is would be much appreciated. Thanks.
It used to be a common technique when working with flags enums.
You use bitwise and between the input value and the flag you want to check, and compare the results with the flag itself. If the input value contains the flag, the condition is true, if not, the condition is false.
Let me illustrate that with a simple example:
Suppose you have this enum:
[Flags]
enum test
{
None = 0, // 0000
One = 1, // 0001
Two = 2, // 0010
Four = 4, // 0100
Eight = 8 // 1000
}
And you have a value you want to test. Let's say 13. When you convert 13 to a four bit binary number you get 1101 - so you can do something like this:
var input = 13;
if(((test)input & test.One) == test.One) // that's testing if 1101 & 0001 = 0001
{
// The result of this condition is true, since 13 is an odd number.
}
However, since .Net 4.0 you can simply use the HasFlag method instead:
if(input.HasFlag(test.One))
{
// The result of this condition is true, since 13 is an odd number.
}
For more information you can read Ending the Great Debate on Enum Flags

Using an enum as an optional parameter

I have several methods in an application I'm working on loaded with optional parameters, some of which are enums. Currently, in order to do that I'm writing methods with a similar type of signature:
public void SomeMethod(string myFirstParam = "", string mySecondParam = "", MyEnum myThirdParam = (MyEnum )(-1)){
if (myThirdParam != (MyEnum ) (-1))
{
//do something with it
}
}
So my first question is, is there some pitfall to this approach I haven't realized, but in time will become painfully aware of, and secondly, is there a more proper - or at least elegant solution to it?
I should say that we control the input to this method, it's used internally, so I'm not worried about someone casting in a value of -1 to gum up the works.
I would suggest using nullable enum in this situation, like this:
public void SomeMethod(string myFirstParam = "",
string mySecondParam = "",
MyEnum? myThirdParam = null)
{
if (myThirdParam.HasValue)
{
var enumValue = myThirdParam.Value;
//do something with it
}
}
and you can use it like this:
SomeMethod(myThirdParam: MyEnum.Something);
Make sure your enum has a default value (equal to zero), that means "none" or "invalid". This would be an appropriate value for your optional parameter's default value.
This is recommended by Microsoft Code Analysis as well, CA1008: Enums should have zero value.
For example:
enum SpeakerType
{
None = 0,
Woofer,
Midrange
Tweeter
}
This way the default keyword provides a value that is sane, but doesn't unintentionally refer to something you don't want it to.
As an example, the BCL uses this same concept. The number of stop bits to use for a SerialPort is defined by the StopBits enum:
public enum StopBits
{
None,
One,
Two,
OnePointFive,
}
However the None value is invalid. In fact,
The SerialPort class throws an ArgumentOutOfRangeException exception when you set the StopBits property to None.
What about :
enum MyEnum {
MISSING = -1,
FirstValue,
SecondValue,
...
}
public void SomeMethod(string myFirstParam = "", string mySecondParam = "", MyEnum myThirdParam = MISSING) {
if (myThirdParam != MISSING)
{
//do something with it
}
}

How to get complex enum value string representation

Let's say I have this enum:
[Flags]
public enum SomeType
{
Val1 = 0,
Val2 = 1,
Val3 = 2,
Val4 = 4,
Val5 = 8,
Val6 = 16,
All = Val1 | Val2 | Val3 | Val4 | Val5 | Val6
}
and some variables:
SomeType easyType = SomeType.Val1 | SomeType.Val2;
SomeType complexType = SomeType.All;
If I want to loop through values of the first enum I can simply do:
foreach(string s in easyType.ToString().Split(','))
{ ... }
However, when I try to apply the same approach to the 'complexType' I get value 'All', which is of course valid because it's also one of possible values of the enum. But, is there a neat way to actually see of what values is the SomeType.All created of? I know I could make a manual loop through all the values like that:
if(complexType.HasFlag(ManualType.Val1) && ...
var result = string.Join(",",
Enum.GetValues(typeof(SomeType))
.Cast<SomeType>()
.Where(v => complexType.HasFlag(v)));
You can write an extension method to avoid repeating yourself.
Maybe you need to enumerate the enum values and test each one:
foreach (SomeType item in Enum.GetValues (typeof (SomeType))
{
if ((complexType & item) == item)
{
//...
}
}
Here's one possible way to do it, building on Danny Chen's answer:
public IEnumerable<T> GetFlags<T>(Predicate<int> hasFlag)
{
return GetEnumFlags<T>().Where(f => hasFlag(f)).Cast<T>();
}
private IEnumerable<int> GetEnumFlags<T>()
{
return Enum.GetValues(typeof(T)).Cast<int>().Where(IsPowerOfTwoOrZero);
}
private bool IsPowerOfTwoOrZero(int v)
{
return ((v & (v-1)) == 0);
}
Usage:
void Main()
{
SomeType easyType = SomeType.Val1 | SomeType.Val2;
SomeType complexType = SomeType.All;
GetFlags<SomeType>(v => easyType.HasFlag((SomeType)v));
GetFlags<SomeType>(v => complexType.HasFlag((SomeType)v));
}
Note this will work for Enums based on types castable to int. You can create similar methods for long etc.
If you're using an enum to represent data that has some deeper level of complexity (arbitrary groups of elements, "darkness" of colour, etc.) and struggling because of that, I'd suggest that an enum is the wrong programming construct to be using.
Using an enum for these tasks will always be error prone: if I add a new colour to your enum, I have to remember to add it to "Bright" or "Dark" too. That makes your code just as error prone for developers as the original problem. What you could do, however, is define a class or struct for colour that has a property indicating whether it's bright or not. Then you'll have clear, understandable functionality - implemented in a way that doesn't give spurious results as when you're trying to misuse a simpler language feature.
That, for example, is why Color is a struct...

Using a bitmask in C#

Let's say I have the following
int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000
and I pass 10 (8 + 2) as a parameter to a method and I want to decode this to mean susan and karen
I know that 10 is 1010
but how can I do some logic to see if a specific bit is checked as in
if (condition_for_karen) // How to quickly check whether effective karen bit is 1
Right now all i can think of is to check whether the number i passed is
14 // 1110
12 // 1100
10 // 1010
8 // 1000
When I have a larger number of actual bits in my real world scenario, this seems impractical, what is a better way using a mask to just check whether or not I meet the condition for just karen?
I can think of shifting left then back then shifting right then back to clear bits other than the one I'm interested in, but this also seems overly complex.
The traditional way to do this is to use the Flags attribute on an enum:
[Flags]
public enum Names
{
None = 0,
Susan = 1,
Bob = 2,
Karen = 4
}
Then you'd check for a particular name as follows:
Names names = Names.Susan | Names.Bob;
// evaluates to true
bool susanIsIncluded = (names & Names.Susan) != Names.None;
// evaluates to false
bool karenIsIncluded = (names & Names.Karen) != Names.None;
Logical bitwise combinations can be tough to remember, so I make life easier on myself with a FlagsHelper class*:
// The casts to object in the below code are an unfortunate necessity due to
// C#'s restriction against a where T : Enum constraint. (There are ways around
// this, but they're outside the scope of this simple illustration.)
public static class FlagsHelper
{
public static bool IsSet<T>(T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
return (flagsValue & flagValue) != 0;
}
public static void Set<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
flags = (T)(object)(flagsValue | flagValue);
}
public static void Unset<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
flags = (T)(object)(flagsValue & (~flagValue));
}
}
This would allow me to rewrite the above code as:
Names names = Names.Susan | Names.Bob;
bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);
bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);
Note I could also add Karen to the set by doing this:
FlagsHelper.Set(ref names, Names.Karen);
And I could remove Susan in a similar way:
FlagsHelper.Unset(ref names, Names.Susan);
*As Porges pointed out, an equivalent of the IsSet method above already exists in .NET 4.0: Enum.HasFlag. The Set and Unset methods don't appear to have equivalents, though; so I'd still say this class has some merit.
Note: Using enums is just the conventional way of tackling this problem. You can totally translate all of the above code to use ints instead and it'll work just as well.
Easy Way:
[Flags]
public enum MyFlags {
None = 0,
Susan = 1,
Alice = 2,
Bob = 4,
Eve = 8
}
To set the flags use logical "or" operator |:
MyFlags f = new MyFlags();
f = MyFlags.Alice | MyFlags.Bob;
And to check if a flag is included use HasFlag:
if(f.HasFlag(MyFlags.Alice)) { /* true */}
if(f.HasFlag(MyFlags.Eve)) { /* false */}
if ( ( param & karen ) == karen )
{
// Do stuff
}
The bitwise 'and' will mask out everything except the bit that "represents" Karen. As long as each person is represented by a single bit position, you could check multiple people with a simple:
if ( ( param & karen ) == karen )
{
// Do Karen's stuff
}
if ( ( param & bob ) == bob )
// Do Bob's stuff
}
I have included an example here which demonstrates how you might store the mask in a database column as an int, and how you would reinstate the mask later on:
public enum DaysBitMask { Mon=0, Tues=1, Wed=2, Thu = 4, Fri = 8, Sat = 16, Sun = 32 }
DaysBitMask mask = DaysBitMask.Sat | DaysBitMask.Thu;
bool test;
if ((mask & DaysBitMask.Sat) == DaysBitMask.Sat)
test = true;
if ((mask & DaysBitMask.Thu) == DaysBitMask.Thu)
test = true;
if ((mask & DaysBitMask.Wed) != DaysBitMask.Wed)
test = true;
// Store the value
int storedVal = (int)mask;
// Reinstate the mask and re-test
DaysBitMask reHydratedMask = (DaysBitMask)storedVal;
if ((reHydratedMask & DaysBitMask.Sat) == DaysBitMask.Sat)
test = true;
if ((reHydratedMask & DaysBitMask.Thu) == DaysBitMask.Thu)
test = true;
if ((reHydratedMask & DaysBitMask.Wed) != DaysBitMask.Wed)
test = true;
To combine bitmasks you want to use bitwise-or. In the trivial case where every value you combine has exactly 1 bit on (like your example), it's equivalent to adding them. If you have overlapping bits however, or'ing them handles the case gracefully.
To decode the bitmasks you and your value with a mask, like so:
if(val & (1<<1)) SusanIsOn();
if(val & (1<<2)) BobIsOn();
if(val & (1<<3)) KarenIsOn();
One other really good reason to use a bitmask vs individual bools is as a web developer, when integrating one website to another, we frequently need to send parameters or flags in the querystring. As long as all of your flags are binary, it makes it much simpler to use a single value as a bitmask than send multiple values as bools. I know there are otherways to send data (GET, POST, etc.), but a simple parameter on the querystring is most of the time sufficient for nonsensitive items. Try to send 128 bool values on a querystring to communicate with an external site. This also gives the added ability of not pushing the limit on url querystrings in browsers

C# function that accepts an Enum item and returns the enum value (not the index)

say I have the following declarations:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
and I want to code it so that I could get the enum value (not the index, like I earlier mentioned):
//should store the value of the Complexity enum member Normal, which is 1
int complexityValueToStore = EnumHelper.GetEnumMemberValue(Complexity.Normal);
//should store the value 4
int priorityValueToStore = EnumHelper.GetEnumMemberValue(Priority.Urgent);
How should this reusable function look like?
tia!
-ren
Revised answer (after question clarification)
No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.
Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.
Original answer
What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:
public static int GetEnumMemberIndex<T>(T element)
where T : struct
{
T[] values = (T[]) Enum.GetValues(typeof(T));
return Array.IndexOf(values, element);
}
You can find the integer value of an enum by casting:
int complexityValueToStore = (int)Complexity.Normal;
The most generic way I know of is to read the value__ field using reflection.
This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.
public static object GetValue(Enum e)
{
return e.GetType().GetField("value__").GetValue(e);
}
Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3)); //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8)); //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64
Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.
I realize this isn't what you asked, but it's something you might appreciate.
I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
int valueOfHigh = Complexity.High - Complexity.Low;
This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;
I find this technique much more aesthetically appealing than casting to int.
I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.
If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.
If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.
However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.
This is the most simple way to solve your problem:
public static void GetEnumMemberValue<T>(T enumItem) where T : struct
{
return (int) Enum.Parse(typeof(T), enumItem.ToString());
}
It works for me.

Categories