I have to build an extension method for each flag type I declare, like so:
public static EventMessageScope SetFlag(this EventMessageScope flags,
EventMessageScope flag, bool value)
{
if (value)
flags |= flag;
else
flags &= ~flag;
return flags;
}
Why isn't there an Enum.SetFlag
like there is an Enum.HasFlag
?
Also, why does this not work always?
public static bool Get(this EventMessageScope flags, EventMessageScope flag)
{
return ((flags & flag) != 0);
}
For example, if I have:
var flag = EventMessageScope.Private;
And check it like:
if(flag.Get(EventMessageScope.Public))
Where EventMessageScope.Public
really is EventMessageScope.Private | EventMessageScope.PublicOnly
, it returns true.
When it's not, because Private
is not public, it's just half public.
The same goes for:
if(flag.Get(EventMessageScope.None))
Which returns false
, except the scope is actually None
(0x0
), when it should always return true?
Why isn't there an Enum.SetFlag like there is an Enum.HasFlag?
HasFlag
as a bitwise operation required more complicated logic and repeating the same flag twice
myFlagsVariable= ((myFlagsVariable & MyFlagsEnum.MyFlag) ==MyFlagsEnum.MyFlag );
so MS decided to implement it.
SetFlag and ClearFlag are concise in C#
flags |= flag;// SetFlag
flags &= ~flag; // ClearFlag
but unfortunately not intuitive. Every time I need to set (or clear) a flag, I'm spending a few seconds (or minutes) to think: what is the name of the method? Why is it not shown in intellisense? Or no, I have to use bitwise operations. Note, that some developers will also ask: what is a bitwise operation?
Should SetFlag and ClearFlag extensions be created - YES to appear in intellisense.
Should SetFlag and ClearFlag extensions be used by developers - NO, because they are not efficient.
We've created extensions in our library's class EnumFlagsHelper like in SomeEnumHelperMethodsThatMakeDoingWhatYouWantEasier, but named the function as SetFlag instead of Include and ClearFlag instead of Remove.
In the body of SetFlag methods ( and in summary comment) I decided to add
Debug.Assert( false, " do not use the extension due to performance reason, use bitwise operation with the explanatory comment instead \n
flags |= flag;// SetFlag")
and a similar message should be added to ClearFlag
Debug.Assert( false, " do not use the extension due to performance reason, use bitwise operation with the explanatory comment instead \n
flags &= ~flag; // ClearFlag ")
I've done something that works for me and that's very simple...
public static T SetFlag<T>(this Enum value, T flag, bool set)
{
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
// note: AsInt mean: math integer vs enum (not the c# int type)
dynamic valueAsInt = Convert.ChangeType(value, underlyingType);
dynamic flagAsInt = Convert.ChangeType(flag, underlyingType);
if (set)
{
valueAsInt |= flagAsInt;
}
else
{
valueAsInt &= ~flagAsInt;
}
return (T)valueAsInt;
}
Usage:
var fa = FileAttributes.Normal;
fa = fa.SetFlag(FileAttributes.Hidden, true);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With