How do you test an enum flag combination? - c#

Let’s say I have an enum flag:
[Flags]
public enum ColorType
{
None = 0,
Red = 1 << 0,
White = 1<<1,
Yellow = 1 << 2,
Blue = 1 << 3,
All = Red | White | Yellow | Blue
}
I have the below function, which parameter is a combination of flag, such as DoSomething( ColorType.Blue | ColorType.Yellow ).
public void DoSomethingr(ColorType theColorTypes)
{
if (theColorTypes.HasFlag(All)) Foo1();
if (theColorTypes.HasFlag(White) && theColorTypes.HasFlag(Red) ) Foo2();
if (!theColorTypes.HasFlag(Blue)) Foo3();
. . .
}
Is there an easy way to test all of possible flag bitwise combination?
[Test]
public void Test1(ColorType.Red | ColorType.Yellow | ColorType.White)
[Test]
public void Test1(ColorType.Red | ColorType.Yellow | ColorType.white | ColorType.Blue)
Thanks

Loop over all the possible values and put it in a TestCaseSource to generate a different test for each enumeration value:
public IEnumerable<ColorType> TestCaseSource
{
get
{
int start = (int)ColorType.None;
int count = (int)ColorType.All - start + 1;
return Enumerable.Range(start, count).Select(i => (ColorType)i);
}
}
[TestCaseSource("TestCaseSource")]
public void Test1(ColorType colorType)
{
// whatever your test is
}

Just my two cents and this could probably be improved to accept 'other' value types as well, but as an alternative when you like extension methods:
public static class EnumExtensions
{
public static bool HasFlags<TEnum>(this TEnum #enum,
TEnum flag,
params TEnum[] flags)
where TEnum : struct
{
var type = typeof(TEnum);
if (!type.IsEnum)
throw new ArgumentException("#enum is not an Enum");
var hasFlagsMethod = type.GetMethod("HasFlag");
var hasFlag = new Func<TEnum, bool>(e =>
{
return (bool)hasFlagsMethod.Invoke(#enum, new object[] { e });
});
// test the first flag argument
if (!hasFlag(flag))
return false;
// test the params flags argument
foreach (var flagValue in flags)
{
if (!hasFlag(flagValue))
return false;
}
return true;
}
}
[Flags]
public enum ColorType
{
None = 0,
Red = 1 << 0,
White = 1 << 1,
Yellow = 1 << 2,
Blue = 1 << 3,
All = Red | White | Yellow | Blue
}
Call it like this:
class Program
{
static void Main(string[] args)
{
var color = ColorType.Red;
Console.WriteLine(color.HasFlags(ColorType.Red)); // true;
Console.WriteLine(color.HasFlags(ColorType.Red, ColorType.Blue)); // false;
color = ColorType.All;
Console.WriteLine(color.HasFlags(ColorType.Red, ColorType.Blue)); // true;
Console.ReadLine();
}
}

Related

Comparison process with enum element values

Enum A
{ a = 10, a1 = 35, ....}
Enum B
{ b = 5, b1 = 20, ..... }
How can I get the int values ​​of any two of the two enum class elements? To compare with these values ​​and destroy the smaller one.
Sorry. Maybe this is what you're looking for?
enumA.CompareTo(enumB) > 0 ? "A is greater than B" : "B is greater than or equal to A";
enumA.CompareTo(enumB) = 0 ? "A is equal to B" : "A is not equal to B";
This should compare two Enum instances (enumA and enumB), and execute the code inserted in place of the strings.
Take this console app as an example to obtain the lowest int from your enum type:
using System;
using System.Linq;
using System.Collections.Generic;
namespace ConsoleApp1 {
class Program {
enum Colors {
blue = 1,
orange = 2,
purple = 3
}
enum Stages {
level1 = 35,
level2 = 62,
level3 = 13
}
public static int getMinEnumValue(Type enumType) {
Array values = Enum.GetValues(enumType);
List<int> intList = ((int[])values).ToList();
int minValue = intList.Min();
return minValue;
}
static void Main(string[] args) {
int minStagegInt = getMinEnumValue(typeof(Stages));
int minColorInt = getMinEnumValue(typeof(Colors));
Console.WriteLine($"Min stage int: {minStagegInt}, which is: {Enum.GetName(typeof(Stages), minStagegInt)}");
Console.WriteLine($"Min color int: {minColorInt}, which is: {Enum.GetName(typeof(Colors), minColorInt)}");
Console.ReadLine();
//keyValue anonymous type
var myInstance1 = new[] { new { a = 10 }, new { a = 35 }, new { a = 3 } };
var myInstance2 = new[] { new { b = 5 }, new { b = 20 } };
var minObject1 = myInstance1.ToList().OrderBy(elem => elem.a).FirstOrDefault();
var minObject2 = myInstance2.ToList().OrderBy(elem => elem.b).FirstOrDefault();
Console.WriteLine($"Min a instance1: {minObject1.ToString()}");
Console.WriteLine($"Min b instance2: {minObject2.ToString()}");
Console.ReadLine();
}
}
}
Output:
Once you are able to get your min, or apply the logic you wish to your enum type, you can destroy or do whatever you want to your obtained enumeration intance of your enum type.
Enum can be cast to int
EnumA valA = EnumA.a; //10
EnumB valB = EnumB.b; //5
if((int)valA < (int)valB) // 10 < 5
{ Destroy(a);}
else {Destroy(b);}
Edit:
public static int CompareAtoB(int a, int b)
{
if(a==b) return 0;
return (a < b) ? 1 : -1;
}
You can now pass any value that you cast when you give as parameter.
int result = CompareAtoB((int)someEnum, (int) otherEnum);
Then act based on result.

Convert a flagged enum to another one

I have a general enum, let's say G that has some flagged values (One = 0 / Two = 1 / Three = 2 / Four = 4 / Five = 8, and so on).
I then have another enum (let's say B) that "extends" G with this kind of pattern : One = G.One / Two = G.Two / Three = G.Three / Four = G.Four (and that's all, no Five in this one).
I finally have have a last enum (let's say C) that also "extends" G with the same pattern type but other values : Three = G.Three / Four = G.Four / Five = G.Five (no One and Two in this one).
I'd like to find a generic function to convert B into C or C into B.
For example, if I have "A valsAsA = A.One | A.Three | A.Four", I'd like a function like this : "B valsAsB = convert(valsAsA);" that would gives me "B.Three | A.Four".
This should be really generic because I have not only A and B enums, but also C, D, E... with different possible enum values, but always values from the generic enum.
Is it possible without checking all possibilities and adapting the function each time I add a new enum ?
An example:
public enum General : int
{
One = 0,
Two = 1,
Three = 2,
Four = 4,
Five = 8
}
public enum A : int
{
One = General.One,
Two = General.Two,
Three = General.Three,
Four = General.Four,
}
public enum B : int
{
Three = General.Three,
Four = General.Four,
Five = General.Five
}
public enum C : int
{
One = General.One,
Three = General.Three,
Five = General.Five
}
public class Test
{
public void testConvert()
{
A valAsA = A.One | A.Three | A.Four;
B valAsB = convertFct(valAsA); // Should give me "B.Three | B.Four"
C valAsC = convertFct(valAsA); // Should give me "C.One | C.Three"
}
}
I tested that :
A valAsA = A.One | A.Three | A.Four;
C valAsC = (C)valAsA;
C valAsCReal = C.One | C.Three; // expected result
with no luck.. valAsC = 6 while valAsCReal = 2...
Thank you very much
Doing this with generics is a little tricky because it is not possible to set up a type constraint that allows enumerations in general (see this question). The best you can do is constraint to struct, IConvertible and do a runtime check, as I do in this example.
If you can cope with that part of the ugliness, the rest is fairly simple:
First, write two methods to convert to and from a General. Since your enums are bit masks, the "conversion" is actually just a binary and operation against the sum of all possible values, which you can obtain using GetValues.
Once you have performed the and operation, you can return an enum of the appropriate type by converting the integer using Enum.ToObject().
static public class ExtensionMethods
{
static public General ToGeneral<T>(this T input) where T : struct, IConvertible
{
if (!typeof(T).IsEnum) throw new ArgumentException("Input must be an enum.");
return (General)((int)(object)input & Enum.GetValues(typeof(General)).Cast<int>().Sum());
}
static public T ToEnum<T>(this General input)
{
if (!typeof(T).IsEnum) throw new ArgumentException("Output type must be an enum.");
return (T)Enum.ToObject(typeof(T), (int)input & Enum.GetValues(typeof(T)).Cast<int>().Sum());
}
}
Once those are written, conversion to and from any enum is easy:
static public TOut Convert<TIn,TOut>(TIn input) where TIn : struct, IConvertible where TOut: struct, IConvertible
{
var general = input.ToGeneral();
return general.ToEnum<TOut>();
}
Test code:
public static void Main()
{
A valAsA = A.One | A.Three | A.Four;
B valAsB = Convert<A, B>(valAsA); // Should give me "B.Three | B.Four"
C valAsC = Convert<A, C>(valAsA); // Should give me "C.One | C.Three"
Console.WriteLine("{0} should equal {1}", valAsB, (B.Three | B.Four));
Console.WriteLine("{0} should equal {1}", valAsC, (C.One | C.Three));
}
Output:
6 should equal 6
Three should equal Three
See the code in action at DotNetFiddle
Damn !!! I could create this incredible function that answer to my question but please... tell me that there is something more elegant... xD
private TRet ConvertIt<TRet, TOrig>(TOrig values) where TOrig : struct, IConvertible where TRet : struct, IConvertible
{
if (!typeof(TOrig).IsEnum ||
!typeof(TRet).IsEnum ||
!typeof(int).IsAssignableFrom(typeof(TOrig)) ||
!typeof(int).IsAssignableFrom(typeof(TRet)))
{
throw new ArgumentException("TOrig and TRet must be an enumerated type extending integer");
}
bool retEnumHasZero = false;
foreach (var flag in Enum.GetValues(typeof(TRet)))
{
if ((int)flag == 0)
{
retEnumHasZero = true;
break;
}
}
if (!retEnumHasZero)
{
throw new ArgumentException("TRet enum must have the 0 flag");
}
Dictionary<int, Enum> valsOrig = new Dictionary<int, Enum>();
foreach (var flag in Enum.GetValues(typeof(TOrig)))
{
valsOrig.Add((int)flag, (Enum)flag);
}
object valuesAsObject = values;
var valuesAsEnum = (Enum)valuesAsObject;
int returnedValue = 0;
foreach (var flag in Enum.GetValues(typeof(TRet)))
{
int flagAsInt = (int)flag;
if (valsOrig.ContainsKey(flagAsInt) && valuesAsEnum.HasFlag(valsOrig[flagAsInt]))
{
returnedValue |= flagAsInt;
}
}
return (TRet)Enum.ToObject(typeof(TRet), returnedValue);
}
Using the function :
A valAsA = A.One | A.Two | A.Three | A.Four;
C valAsC = ConvertIt<C, A>(valAsA);
Edit : This implementation looks better :
private T ConvertIt<T>(Enum values) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Type to return must be an enumerated type");
}
if (!Enum.IsDefined(typeof(T), 0))
{
throw new ArgumentException("Type to return enum must have the 0 flag");
}
int returnedValue = 0;
foreach (var flag in Enum.GetValues(values.GetType()))
{
int flagAsInt = (int)flag;
if (values.HasFlag((Enum)flag) && Enum.IsDefined(typeof(T), flagAsInt))
{
returnedValue |= flagAsInt;
}
}
return (T)Enum.ToObject(typeof(T), returnedValue);
}
Using the function :
A valAsA = A.One | A.Two | A.Three | A.Four;
C valAsC = ConvertIt<C>(valAsA);
Finally, with the help of John Wu, here is the final function =>
private T ConvertIt<T>(Enum input) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Type to return must be an enumerated type");
}
return (T)Enum.ToObject(typeof(T), (int)(object)input & Enum.GetValues(typeof(T)).Cast<int>().Sum());
}

Enum flag attribute C#

i'be looked some same topics but havn't find what i'm looking for
I should use flag enum flag atribute and check if my data is in one of the collections of this enum
For example, enum:
[Flags]
private enum MyEnum {
Apple,
Orange,
Tomato,
Potato
Melon,
Watermelon,
Fruit = Apple | Orange,
Vegetable = Tomato | Potato,
Berry = Melon | Watermelon,
}
In the method i should check a input data. How can i do it?
private void Checking(string data){
if(MyEnum.Fruit contains data) MessageBox.Show("Fruit");
if(MyEnum.Vegetable contains data) MessageBox.Show("Vegetables");
if(MyEnum.Berry contains data) MessageBox.Show("Berry");
}
What should be instead of "contains data"?
UPDATE
private void ZZZ(){
Cheching("Apple");
}
First of, you need to manually number your values with the powers-of-2 sequence :
[Flags]
private enum MyEnum
{
None = 0, // often useful
Apple = 1,
Orange = 2,
Tomato = 4,
Potato = 8,
Melon = 16,
Watermelon = 32,
Fruit = Apple | Orange,
Vegetable = Tomato | Potato,
Berry = Melon | Watermelon,
}
The [Flags] attribute is not strictly necessary, it only controls the ToString() behaviour.
And to check whether a string matches your value you'll have to make it an enum first:
private void Checking(string data)
{
MyEnum v = (MyEnum) Enum.Parse(typeof(MyEnum), data);
if((MyEnum.Fruit & v) != 0) MessageBox.Show("It's a Fruit");
...
}
But do note that interchanging between Enum and string like this with Parse() is limited.
In addition to Henk Holterman's solution you may use extension methods:
[Flags]
private enum MyEnum {
None = 0,
Apple = 1,
Orange = 2,
Tomato = 4,
Potato = 8,
Melon = 16,
Watermelon = 32,
Berry = Melon | Watermelon,
Fruit = Apple | Orange,
Vegetable = Potato | Tomato
}
private static class MyEnumExtensions {
public static Boolean IsFruit(this MyEnum value) {
return (value & MyEnum.Fruit) == MyEnum.Fruit;
}
public static Boolean IsVegetable(this MyEnum value) {
return (value & MyEnum.Vegetable) == MyEnum.Vegetable;
}
public static Boolean IsBerry(this MyEnum value) {
return (value & MyEnum.Berry) == MyEnum.Berry;
}
}
...
MyEnum data = ...
if (data.IsBerry()) {
MessageBox.Show("Berry");
}
You also can use the HasFlag-method of the Enum-class. As Henk pointed out will need to assign the values to your enum manually using values of the powers-of-2 sequence.
[Flags]
private enum MyEnum
{
Apple = 1,
Orange = 2,
Tomato = 4,
Potato = 8,
Melon 16,
Watermelon = 32,
Fruit = Apple | Orange,
Vegetable = Tomato | Potato,
Berry = Melon | Watermelon,
}
Then, to check you could use the following method which is working for all composed parts of your enumeration:
void Cheking(string data)
{
// Get the enum value of the string passed to the method
MyEnum myEnumData;
if (Enum.TryParse<MyEnum>(data, out myEnumData))
{
// If the string was a valid enum value iterate over all the value of
// the underlying enum type
var values = Enum.GetValues(typeof(MyEnum)).OfType<MyEnum>();
foreach (var value in values)
{
// If the value is not a power of 2 it is a composed one. If it furthermore
// has the flag passed to the method this is one we searched.
var isPowerOfTwo = (value != 0) && ((value & (value - 1)) == 0);
if (!isPowerOfTwo && value.HasFlag(myEnumData))
{
MessageBox.Show(value.ToString());
}
}
}
// In case an invalid value had been passed to the method
// display an error message.
else
{
MessageBox.Show("Invalid Value");
}
}
Or to write it in a shorter way using LINQ:
var results = Enum.GetValues(typeof(MyEnum))
.OfType<MyEnum>()
.Select(x => new { Value = x, IsPowerOfTwo = (x != 0) && ((x & (x - 1)) == 0) } )
.Where(x => !x.IsPowerOfTwo && x.Value.HasFlag(myEnumData))
.Select(x => x.Value.ToString());
This will give an IEnumerable<string> containing the results. In case that myEnumData has a value of MyEnum.Apple the result will contain just the value "Fruit".
as #Henk Holterman has suggested, you need first to assign values to the enum.
All values should be a power of 2 (and avoid using 0, except for the special case of "None")
It should look something like this:
MyEnum eVal= (MyEnum ) Enum.Parse( typeof(MyEnum), data, true );
if((MyEnum.Fruit & eVal) != 0) MessageBox.Show("Fruit");
You might want to read more about bitwise and boolean algebra.

Loop through bitwise enum values which have just a single bit field

I have multiple flags enums defined in code similar to the following
[Flags]
public enum Colors
{
None = 0,
Red = 1,
Green = 2,
Blue = 4,
Purple = Red | Blue,
Brown = Red | Green,
}
The following code produces the following output
Colors color1 = Colors.Red | Colors.Blue;
Colors color2 = Colors.Purple;
string s1 = color1.ToString(); // Sets s1 to "Purple"
string s2 = color2.ToString(); // Sets s2 to "Purple"
I want a method that outputs the individual bits of a bitwise enum, even if a matching combination is defined.
private void Foo()
{
Colors color1 = Colors.Red | Colors.Blue;
Colors color2 = Colors.Purple;
string s1 = CreateColumnString(color1); // Sets s1 to "Red|Blue"
string s2 = CreateColumnString(color2); // Sets s2 to "Red|Blue"
}
I thought I could loop through all the values of an enum and check if the value is a power of two. But I can't figure out how to get the underlying value of the Enum argument.
private string CreateColumnString(object value)
{
//is this an enum with Flags attribute?
if (value is Enum && value.GetType().GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0)
{
Enum e = (Enum)value;
//Get a list of Enum values set in this flags enum
IEnumerable<Enum> setValues =
Enum.GetValues(value.GetType())
.Cast<Enum>()
.Where(eachEnum => IsPowerOfTwo(eachEnum) && value.HasFlag(eachEnum));
return string.Join("|", setValues);
}
else
{
return value != null ? value.ToString() : string.Empty;
}
return str;
}
private static bool IsPowerOfTwo(Enum e)
{
int x = (int)e; //ERROR cannot convert type 'System.Enum' to 'ulong'
return (x != 0) && ((x & (x - 1)) == 0);
}
There may be better ways of doing this, but this should do what you are looking for:
private static string AsString<T>(this T values)
{
Enum v = (Enum)Convert.ChangeType(values, typeof(Enum));
Array array = Enum.GetValues(typeof(T));
IEnumerable<Enum> setFlags = array
.Cast<Enum>()
.Where(c => v.HasFlag(c) && IsDistinctValue(c));
return values.Equals(default(T))
? default(T).ToString()
: string.Join("|", setFlags.Where(c => Convert.ToInt32(c) != 0).Select(c => c.ToString()));
}
private static bool IsDistinctValue(Enum value)
{
int current = Convert.ToInt32(value) >> 1;
while (current > 0)
{
if ((Convert.ToInt32(value) & current) != 0)
{
return false;
}
current >>= 1;
}
return true;
}
It will essentially list the values for the set flags, except those that "contain" other flags. It figures this out by taking the value that is being tested, decrementing it towards zero and check whether the original value has that decremented value set as a flag. Finally, it will remove the "None" value, unless no flag is set.
Use it like so:
Colors c = Colors.Purple;
Console.WriteLine(c.AsString());
Here's another approach. I figure the more options you have, the better :)
public static class EnumHelpers
{
public static string ToStringExtended<T>(this Enum e)
{
if (!(e.GetType().GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0))
return e.ToString();
List<string> eNames = new List<string>();
foreach (T fish in Enum.GetValues(typeof(T)))
{
Enum num = fish as Enum;
if (e.HasFlag(num) && Convert.ToInt32(fish) != 0 && Convert.ToInt32(fish) != Convert.ToInt32(e))
eNames.Add(fish.ToString());
}
return eNames.Count > 1 ? String.Join("|", eNames.ToArray()) : e.ToString();
}
}
The usage is almost identical to what Fredirk proposed:
Colors c = Colors.Purple;
Console.WriteLine(c.ToStringExtended<Colors>());
// Output : Red|Blue
You can use the HasFlag method:
.Where(e.HasFlag)
However, I think that your Enum.GetValues call will also get the multi-bit values that your enum type names.
EDIT:
Here's another approach that you might get to work:
if (Enum.GetUnderlyingType(e.GetType()) != typeof(int))
throw new NotImplementedException();
var list = new List<Enum>();
for (int i = 1; i != 0; i <<= 1)
{
var eachEnum = (Enum)(Enum.ToObject(e.GetType(), i));
if (e.HasFlag(eachEnum))
list.Add(eachEnum);
}
return string.Join(" | ", list);
An answer in 4 lines of code not counting the method signature.
private static string CreateColumnString(Colors value)
{
// This is how we do it in embedded programming in C
// In C we wouldn't need to convert, but alas in C# we do
// So first ...
var num = Convert.ToByte(value);
// ToUint16 would work as well, but ToByte makes your intentions clearer
// Then bitwise '& 'every bit position you care about to compose your string
// For example: 0b0011 & 0b1111 = 0b0011 (3 AND 15 = 3)
var s = (num & 1) > 0 ? "Red" : "";
s = (num & 2) > 0 ? s + "|Green": s;
return (num & 2) > 0 ? s + "|Blue" : s;
}

System.Enum combinations with Flags

Consider the following enumeration:
[System.Flags]
public enum EnumType: int
{
None = 0,
Black = 2,
White = 4,
Both = Black | White,
Either = ???, // How would you do this?
}
Currently, I have written an extension method:
public static bool IsEither (this EnumType type)
{
return
(
((type & EnumType.Major) == EnumType.Major)
|| ((type & EnumType.Minor) == EnumType.Minor)
);
}
Is there a more elegant way to achieve this?
UPDATE: As evident from the answers, EnumType.Either has no place inside the enum itself.
With flags enums, an "any of" check can be generalised to (value & mask) != 0, so this is:
public static bool IsEither (this EnumType type)
{
return (type & EnumType.Both) != 0;
}
assuming you fix the fact that:
Both = Black | White
(as Black & White is an error, this is zero)
For completeness, an "all of" check can be generalised to (value & mask) == mask.
Why not simply:
public enum EnumType
{
// Stuff
Either = Black | White
}
How about:
[System.Flags]
public enum EnumType: int
{
None = 0,
Black = 1,
White = 2,
Both = Black | White,
Either = None | Both
}

Categories