Related
I have my own class using the MathDotNet package (more precisely, the Vector<double> class from namespace MathNet.Numerics.LinearAlgebra). The Vector<double> class has a method
public double At(int index)
that returns the double value of the specified index. Internally, the Vector<double> class uses a double[] for that storage. I think it is not possible to directly access the internal double[].
class TwoVectors
{
private Vector<double> v1, v2;
// initializes the vectors v1 and v2, both have length 2.
public TwoVectors(double[] entries1, double[] entries2)
{
if (entries1 == null || entries2 == null ||
entries1.Length != 2 || entries2.Length != 2)
throw new ArgumentException("Erroneous input!");
v1 = Vector<double>.Build.Dense(entries1);
v2 = Vector<double>.Build.Dense(entries2);
}
// gives a copy of the vector data.
public double[] ArrayData
{
get
{
return new double[] { v1.At(0), v1.At(1), v2.At(0), v2.At(1) };
}
}
}
But I would like the Getter not to return a copy of the vector data but the actual vector data, so that future changes are reflected in the vectors.
I.e. if I call
public static Main()
{
TwoVectors twoVec = new TwoVectors(new double[] {1, 2}, new double[] {3, 4});
twoVec.ArrayData[0] = 42;
double[] arrayData = mc.ArrayData; // this now contains {1, 2, 3, 4}
}
then I would like arrayData to contain {42, 2, 3, 4} instead of {1, 2, 3, 4}, as it does now.
I believe I can do this with pointers, but I don't know how!
I thought I could write
public double[] ArrayData
{
get
{
unsafe { return new double*[] { &v1.At(0), &v1.At(1), &v2.At(0), &v2.At(1) }; }
}
}
but the compiler tells me that the address of v1.At(0) and the other ones could not be gotten (Why?).
Also with pointers, I guess I cannot write stuff like
twoVec.ArrayData[0] = 42;
double[] arrayData = mc.ArrayData;
but something with * or & or ->, so there must be some other way... Any ideas?
PS: I know I can write an indexer for my class that looks something like this:
public double this[int i]
{
set
{
switch (i)
{
case 0: v1.At(0, value); break;
case 1: v1.At(1, value); break;
case 2: v2.At(0, value); break;
case 3: v2.At(1, value); break;
default: throw new IndexOutOfRangeException("Index must range from 0 to 3!");
}
}
}
(with method Vector<double>.At(int index, double value) being the setter counterpart to the getter method from the top of the thread)
BUT I want to know if there is a direct way to make statements like
twoVec.ArrayData[0] = 42;
work as expected (i.e. make a real change in the vectors).
If I have a variable holding a flags enum, can I somehow iterate over the single-bit values in that specific variable? Or do I have to use Enum.GetValues to iterate over the entire enum and check which ones are set?
static IEnumerable<Enum> GetFlags(Enum input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
if (input.HasFlag(value))
yield return value;
}
Here is a Linq solution to the problem.
public static IEnumerable<Enum> GetFlags(this Enum e)
{
return Enum.GetValues(e.GetType()).Cast<Enum>().Where(e.HasFlag);
}
There aren't any builtin methods to get each component as far as I know. But here's one way you can get them:
[Flags]
enum Items
{
None = 0x0,
Foo = 0x1,
Bar = 0x2,
Baz = 0x4,
Boo = 0x6,
}
var value = Items.Foo | Items.Bar;
var values = value.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (Items)Enum.Parse(typeof(Items), v));
// This method will always end up with the most applicable values
value = Items.Bar | Items.Baz;
values = value.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (Items)Enum.Parse(typeof(Items), v)); // Boo
I adapted what Enum does internally to generate the string to instead return the flags. You can look at the code in reflector and should be more or less equivalent. Works well for general use cases where there are values which contain multiple bits.
static class EnumExtensions
{
public static IEnumerable<Enum> GetFlags(this Enum value)
{
return GetFlags(value, Enum.GetValues(value.GetType()).Cast<Enum>().ToArray());
}
public static IEnumerable<Enum> GetIndividualFlags(this Enum value)
{
return GetFlags(value, GetFlagValues(value.GetType()).ToArray());
}
private static IEnumerable<Enum> GetFlags(Enum value, Enum[] values)
{
ulong bits = Convert.ToUInt64(value);
List<Enum> results = new List<Enum>();
for (int i = values.Length - 1; i >= 0; i--)
{
ulong mask = Convert.ToUInt64(values[i]);
if (i == 0 && mask == 0L)
break;
if ((bits & mask) == mask)
{
results.Add(values[i]);
bits -= mask;
}
}
if (bits != 0L)
return Enumerable.Empty<Enum>();
if (Convert.ToUInt64(value) != 0L)
return results.Reverse<Enum>();
if (bits == Convert.ToUInt64(value) && values.Length > 0 && Convert.ToUInt64(values[0]) == 0L)
return values.Take(1);
return Enumerable.Empty<Enum>();
}
private static IEnumerable<Enum> GetFlagValues(Type enumType)
{
ulong flag = 0x1;
foreach (var value in Enum.GetValues(enumType).Cast<Enum>())
{
ulong bits = Convert.ToUInt64(value);
if (bits == 0L)
//yield return value;
continue; // skip the zero value
while (flag < bits) flag <<= 1;
if (flag == bits)
yield return value;
}
}
}
The extension method GetIndividualFlags() gets all the individual flags for a type. So values containing multiple bits are left out.
var value = Items.Bar | Items.Baz;
value.GetFlags(); // Boo
value.GetIndividualFlags(); // Bar, Baz
Coming back at this a few years later, with a bit more experience, my ultimate answer for single-bit values only, moving from lowest bit to highest bit, is a slight variant of Jeff Mercado's inner routine:
public static IEnumerable<Enum> GetUniqueFlags(this Enum flags)
{
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<Enum>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value))
{
yield return value;
}
}
}
It seems to work, and despite my objections of some years ago, I use HasFlag here, since it's far more legible than using bitwise comparisons and the speed difference is insignificant for anything I'll be doing. (It's entirely possible they've improved the speed of HasFlags since then anyway, for all I know...I haven't tested.)
Going off of #Greg's method, but adding a new feature from C# 7.3, the Enum constraint:
public static IEnumerable<T> GetUniqueFlags<T>(this T flags)
where T : Enum // New constraint for C# 7.3
{
foreach (Enum value in Enum.GetValues(flags.GetType()))
if (flags.HasFlag(value))
yield return (T)value;
}
The new constraint allows this to be an extension method, without having to cast through (int)(object)e, and I can use the HasFlag method and cast directly to T from value.
C# 7.3 also added constraints to for delegates and unmanaged.
+1 for the answer provided by #RobinHood70. I found that a generic version of the method was convenient for me.
public static IEnumerable<T> GetUniqueFlags<T>(this Enum flags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException("The generic type parameter must be an Enum.");
if (flags.GetType() != typeof(T))
throw new ArgumentException("The generic type parameter does not match the target type.");
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<T>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value as Enum))
{
yield return value;
}
}
}
EDIT
And +1 for #AustinWBryan for bringing C# 7.3 into the solution space.
public static IEnumerable<T> GetUniqueFlags<T>(this T flags) where T : Enum
{
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<T>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value as Enum))
{
yield return value;
}
}
}
Extension method using the new Enum constraint and generics to prevent casting:
public static class EnumExtensions
{
public static T[] GetFlags<T>(this T flagsEnumValue) where T : Enum
{
return Enum
.GetValues(typeof(T))
.Cast<T>()
.Where(e => flagsEnumValue.HasFlag(e))
.ToArray();
}
}
Continuing in my efforts to make the code shorter, this is my latest version of the routine. (I'm the OP...long story.) As discussed previously, this ignores None and multi-bit values.
Note that this uses an Enum constraint and a var pattern, so will require at least C# 7.3.
public static IEnumerable<T> GetUniqueFlags<T>(this T value)
where T : Enum
{
var valueLong = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
foreach (var enumValue in value.GetType().GetEnumValues())
{
if (
enumValue is T flag // cast enumValue to T
&& Convert.ToUInt64(flag, CultureInfo.InvariantCulture) is var bitValue // convert flag to ulong
&& (bitValue & (bitValue - 1)) == 0 // is this a single-bit value?
&& (valueLong & bitValue) != 0 // is the bit set?
)
{
yield return flag;
}
}
}
Wasn't satisfied with the answers above, although they were the start.
After piecing together some different sources here:
Previous poster in this thread's SO QnA
Code Project Enum Flags Check Post
Great Enum<T> Utility
I created this so let me know what you think.
Parameters:
bool checkZero: tells it to allow 0 as a flag value. By default input = 0 returns empty.
bool checkFlags: tells it to check whether the Enum is decorated w/ the [Flags] attribute.
PS. I don't have time right now to figure out the checkCombinators = false alg which will force it to ignore any enum values which are combinations of bits.
public static IEnumerable<TEnum> GetFlags<TEnum>(this TEnum input, bool checkZero = false, bool checkFlags = true, bool checkCombinators = true)
{
Type enumType = typeof(TEnum);
if (!enumType.IsEnum)
yield break;
ulong setBits = Convert.ToUInt64(input);
// if no flags are set, return empty
if (!checkZero && (0 == setBits))
yield break;
// if it's not a flag enum, return empty
if (checkFlags && !input.GetType().IsDefined(typeof(FlagsAttribute), false))
yield break;
if (checkCombinators)
{
// check each enum value mask if it is in input bits
foreach (TEnum value in Enum<TEnum>.GetValues())
{
ulong valMask = Convert.ToUInt64(value);
if ((setBits & valMask) == valMask)
yield return value;
}
}
else
{
// check each enum value mask if it is in input bits
foreach (TEnum value in Enum <TEnum>.GetValues())
{
ulong valMask = Convert.ToUInt64(value);
if ((setBits & valMask) == valMask)
yield return value;
}
}
}
This makes use of the Helper Class Enum<T> found here that I updated to use yield return for GetValues:
public static class Enum<TEnum>
{
public static TEnum Parse(string value)
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
public static IEnumerable<TEnum> GetValues()
{
foreach (object value in Enum.GetValues(typeof(TEnum)))
yield return ((TEnum)value);
}
}
Finally, here's a example of using it:
private List<CountType> GetCountTypes(CountType countTypes)
{
List<CountType> cts = new List<CountType>();
foreach (var ct in countTypes.GetFlags())
cts.Add(ct);
return cts;
}
What I did was change my approach, instead of typing the input parameter of the method as the enum type, I typed it as an array of the enum type (MyEnum[] myEnums), this way I just iterate through the array with a switch statement inside the loop.
Here's yet another C# 7.3 solution using Linq
using System;
using System.Collections.Generic;
using System.Linq;
public static class FlagEnumExtensions
{
public static IEnumerable<T> GetFlags<T>(this T en) where T : struct, Enum
{
return Enum.GetValues<T>().Where(member => en.HasFlag(member)).ToArray();
}
}
Edit: added .ToArray() to prevent multiple enumerations.
You dont need to iterate all values. just check your specific flags like so:
if((myVar & FlagsEnum.Flag1) == FlagsEnum.Flag1)
{
//do something...
}
or (as pstrjds said in comments) you can check for use it like:
if(myVar.HasFlag(FlagsEnum.Flag1))
{
//do something...
}
Building upon Greg's answer above, this also takes care of the case where you have a value 0 in your enum, such as None = 0. In which case, it should not iterate over that value.
public static IEnumerable<Enum> ToEnumerable(this Enum input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
if (input.HasFlag(value) && Convert.ToInt64(value) != 0)
yield return value;
}
Would anyone know how to improve upon this even further so that it can handle the case where all flags in the enum are set in a super smart way that could handle all underlying enum type and the case of All = ~0 and All = EnumValue1 | EnumValue2 | EnumValue3 | ...
You can use an Iterator from the Enum. Starting from the MSDN code:
public class DaysOfTheWeek : System.Collections.IEnumerable
{
int[] dayflag = { 1, 2, 4, 8, 16, 32, 64 };
string[] days = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
public string value { get; set; }
public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < days.Length; i++)
{
if value >> i & 1 == dayflag[i] {
yield return days[i];
}
}
}
}
It's not tested, so if I made a mistake feel free to call me out. (obviously it's not re-entrant.) You'd have to assign value beforehand, or break it out into another function that uses enum.dayflag and enum.days. You might be able to go somewhere with the outline.
All the answers work well with simple flags, you're probably going to get into issues when flags are combined.
[Flags]
enum Food
{
None=0
Bread=1,
Pasta=2,
Apples=4,
Banana=8,
WithGluten=Bread|Pasta,
Fruits = Apples | Banana,
}
probably need to add a check to test if the enum value it self is a combination.
You'd probably need something like posted here by Henk van Boeijen
to cover your requirement (you need to scroll down a bit)
When it comes to performance, which is important in game development, all solutions given are terrible because of garbage allocation and slow speed. This is a garbage free, over 100 times faster solution than accepted answer.
[Flags]
public enum PersonalTraits : short
{
None = 1 << 0,
Strength = 1 << 1,
Agility = 1 << 2,
Attack = 1 << 3,
Defence = 1 << 4,
Vitality = 1 << 5,
Stamina = 1 << 6,
Accuracy = 1 << 7,
Perception = 1 << 8,
Charisma = 1 << 9,
}
PersonalTraits athlete = PersonalTraits.Stamina | PersonalTraits.Strength;
for (short i = 0, value = 0; value <= (short)PersonalTraits.Charisma; i++, value = (short)(1 << i))
if (((short)athlete & value) != 0)
yield return (PersonalTraits)value;
It could be aswell as the following code:
public static string GetEnumString(MyEnum inEnumValue)
{
StringBuilder sb = new StringBuilder();
foreach (MyEnum e in Enum.GetValues(typeof(MyEnum )))
{
if ((e & inEnumValue) != 0)
{
sb.Append(e.ToString());
sb.Append(", ");
}
}
return sb.ToString().Trim().TrimEnd(',');
}
It goes inside if only when the enum value is contained on the value
You can do it directly by converting to int but you will loose type checking.
I think the best way is use something similar to my proposition. It keep the proper type all the way. No conversion required. It is not perfect due to boxing which will add a little hit in performance.
Not perfect (boxing), but it does the job with no warning...
/// <summary>
/// Return an enumerators of input flag(s)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static IEnumerable<T> GetFlags<T>(this T input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
{
if ((int) (object) value != 0) // Just in case somebody has defined an enum with 0.
{
if (((Enum) (object) input).HasFlag(value))
yield return (T) (object) value;
}
}
}
Usage:
FileAttributes att = FileAttributes.Normal | FileAttributes.Compressed;
foreach (FileAttributes fa in att.GetFlags())
{
...
}
I would like to choose the third element from an enum containing three elements while knowing which two I have already chosen. What is the most effcient way of comparing enums?
EDIT:
So far I have come up with the following:
Drawable.Row alternateChoice = (Drawable.Row)ExtensionMethods.Extensions.DefaultChoice(new List<int>() { (int)chosenEnum1, (int)chosenEnum2 }, new List<int>() { 0, 1, 2 });
Drawable.Row is the enum, the first list is what has already been chosen, and the second list contains the possible choices. The definition of DefaultChoice follows. I am aware it has quadratic time-complexity which is why I'm asking for a better solution:
public static int DefaultChoice(List<int> chosen, List<int> choices)
{
bool found = false;
foreach (int choice in choices)
{
foreach (int chosenInt in chosen)
{
if (chosenInt == choice)
{
found = true;
break;
}
}
if (!found)
{
return choice;
}
found = false;
}
return -1;
}
Try this:
List<MyEnum> selectedValues = new List<MyEnum>();
selectedValues.Add(MyEnum.firstValue); // Add selected value
selectedValues.Add(MyEnum.secondValue); // Add selected value
List<MyEnum> valuesLeftOver = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToList();
valuesLeftOver = valuesLeftOver.Except(selectedValues).ToList<MyEnum>(); // This will result in the remaining items (third item) being in valuesLeftOver list.
Short and simple code.
Try not to worry about efficiency too much. Optimization algorithms are so powerful these days that you will probably get same assembly code doing this rather than trying to do it manually.
[Flags]
public enum NumberEnum : byte
{
None = 0,
One = 1,
Two = 2,
Three = 4
};
public string GetRemainingEnumItem(NumberEnum filterFlags = 0)
{
if (((filterFlags & NumberEnum.One) == NumberEnum.One) && ((filterFlags & NumberEnum.Two) == NumberEnum.Two))
{
//1 & 2 are selected so item 3 is what you want
}
if (((filterFlags & NumberEnum.One) == NumberEnum.One) && ((filterFlags & NumberEnum.Three) == NumberEnum.Three))
{
//1 & 3 are selected so item 2 is what you want
}
if (((filterFlags & NumberEnum.Three) == NumberEnum.Three) && ((filterFlags & NumberEnum.Two) == NumberEnum.Two))
{
//2 & 3 are selected so item 1 is what you want
}
}
This is how you call it:
var testVal = NumberEnum.One | NumberEnum.Two;
var resultWillEqual3 = GetRemainingEnumItem(testVal);
You might like to try this approach...
public enum Marx {chico, groucho, harpo};
public Marx OtherOne(Marx x, Marx y)
{
return (Marx)((int)Marx.chico + (int)Marx.groucho + (int)Marx.harpo - (int)x - (int)y);
} // OtherOne
// ...
Marx a = Marx.harpo;
Marx b = Marx.chico;
Marx other = OtherOne(a, b); // picks groucho
This may be of use if you are using an enum marked as [Flags]...
public class Enums2
{
[Flags] public enum Bits {none = 0, aBit = 1, bBit = 2, cBit = 4, dBit = 8};
public static readonly Bits allBits;
static Enums2()
{
allBits = Bits.none;
foreach (Bits b in Enum.GetValues(typeof(Bits)))
{
allBits |= b;
}
} // static ctor
public static Bits OtherBits(Bits x)
// Returns all the Bits not on in x
{
return x ^ allBits;
} // OtherBits
// ...
Bits someBits = Bits.aBit | Bits.dBit;
Bits missingBits = OtherBits(someBits); // gives bBit and cBit
} // Enums2
If I have a variable holding a flags enum, can I somehow iterate over the single-bit values in that specific variable? Or do I have to use Enum.GetValues to iterate over the entire enum and check which ones are set?
static IEnumerable<Enum> GetFlags(Enum input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
if (input.HasFlag(value))
yield return value;
}
Here is a Linq solution to the problem.
public static IEnumerable<Enum> GetFlags(this Enum e)
{
return Enum.GetValues(e.GetType()).Cast<Enum>().Where(e.HasFlag);
}
There aren't any builtin methods to get each component as far as I know. But here's one way you can get them:
[Flags]
enum Items
{
None = 0x0,
Foo = 0x1,
Bar = 0x2,
Baz = 0x4,
Boo = 0x6,
}
var value = Items.Foo | Items.Bar;
var values = value.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (Items)Enum.Parse(typeof(Items), v));
// This method will always end up with the most applicable values
value = Items.Bar | Items.Baz;
values = value.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (Items)Enum.Parse(typeof(Items), v)); // Boo
I adapted what Enum does internally to generate the string to instead return the flags. You can look at the code in reflector and should be more or less equivalent. Works well for general use cases where there are values which contain multiple bits.
static class EnumExtensions
{
public static IEnumerable<Enum> GetFlags(this Enum value)
{
return GetFlags(value, Enum.GetValues(value.GetType()).Cast<Enum>().ToArray());
}
public static IEnumerable<Enum> GetIndividualFlags(this Enum value)
{
return GetFlags(value, GetFlagValues(value.GetType()).ToArray());
}
private static IEnumerable<Enum> GetFlags(Enum value, Enum[] values)
{
ulong bits = Convert.ToUInt64(value);
List<Enum> results = new List<Enum>();
for (int i = values.Length - 1; i >= 0; i--)
{
ulong mask = Convert.ToUInt64(values[i]);
if (i == 0 && mask == 0L)
break;
if ((bits & mask) == mask)
{
results.Add(values[i]);
bits -= mask;
}
}
if (bits != 0L)
return Enumerable.Empty<Enum>();
if (Convert.ToUInt64(value) != 0L)
return results.Reverse<Enum>();
if (bits == Convert.ToUInt64(value) && values.Length > 0 && Convert.ToUInt64(values[0]) == 0L)
return values.Take(1);
return Enumerable.Empty<Enum>();
}
private static IEnumerable<Enum> GetFlagValues(Type enumType)
{
ulong flag = 0x1;
foreach (var value in Enum.GetValues(enumType).Cast<Enum>())
{
ulong bits = Convert.ToUInt64(value);
if (bits == 0L)
//yield return value;
continue; // skip the zero value
while (flag < bits) flag <<= 1;
if (flag == bits)
yield return value;
}
}
}
The extension method GetIndividualFlags() gets all the individual flags for a type. So values containing multiple bits are left out.
var value = Items.Bar | Items.Baz;
value.GetFlags(); // Boo
value.GetIndividualFlags(); // Bar, Baz
Coming back at this a few years later, with a bit more experience, my ultimate answer for single-bit values only, moving from lowest bit to highest bit, is a slight variant of Jeff Mercado's inner routine:
public static IEnumerable<Enum> GetUniqueFlags(this Enum flags)
{
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<Enum>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value))
{
yield return value;
}
}
}
It seems to work, and despite my objections of some years ago, I use HasFlag here, since it's far more legible than using bitwise comparisons and the speed difference is insignificant for anything I'll be doing. (It's entirely possible they've improved the speed of HasFlags since then anyway, for all I know...I haven't tested.)
Going off of #Greg's method, but adding a new feature from C# 7.3, the Enum constraint:
public static IEnumerable<T> GetUniqueFlags<T>(this T flags)
where T : Enum // New constraint for C# 7.3
{
foreach (Enum value in Enum.GetValues(flags.GetType()))
if (flags.HasFlag(value))
yield return (T)value;
}
The new constraint allows this to be an extension method, without having to cast through (int)(object)e, and I can use the HasFlag method and cast directly to T from value.
C# 7.3 also added constraints to for delegates and unmanaged.
+1 for the answer provided by #RobinHood70. I found that a generic version of the method was convenient for me.
public static IEnumerable<T> GetUniqueFlags<T>(this Enum flags)
{
if (!typeof(T).IsEnum)
throw new ArgumentException("The generic type parameter must be an Enum.");
if (flags.GetType() != typeof(T))
throw new ArgumentException("The generic type parameter does not match the target type.");
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<T>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value as Enum))
{
yield return value;
}
}
}
EDIT
And +1 for #AustinWBryan for bringing C# 7.3 into the solution space.
public static IEnumerable<T> GetUniqueFlags<T>(this T flags) where T : Enum
{
ulong flag = 1;
foreach (var value in Enum.GetValues(flags.GetType()).Cast<T>())
{
ulong bits = Convert.ToUInt64(value);
while (flag < bits)
{
flag <<= 1;
}
if (flag == bits && flags.HasFlag(value as Enum))
{
yield return value;
}
}
}
Extension method using the new Enum constraint and generics to prevent casting:
public static class EnumExtensions
{
public static T[] GetFlags<T>(this T flagsEnumValue) where T : Enum
{
return Enum
.GetValues(typeof(T))
.Cast<T>()
.Where(e => flagsEnumValue.HasFlag(e))
.ToArray();
}
}
Continuing in my efforts to make the code shorter, this is my latest version of the routine. (I'm the OP...long story.) As discussed previously, this ignores None and multi-bit values.
Note that this uses an Enum constraint and a var pattern, so will require at least C# 7.3.
public static IEnumerable<T> GetUniqueFlags<T>(this T value)
where T : Enum
{
var valueLong = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
foreach (var enumValue in value.GetType().GetEnumValues())
{
if (
enumValue is T flag // cast enumValue to T
&& Convert.ToUInt64(flag, CultureInfo.InvariantCulture) is var bitValue // convert flag to ulong
&& (bitValue & (bitValue - 1)) == 0 // is this a single-bit value?
&& (valueLong & bitValue) != 0 // is the bit set?
)
{
yield return flag;
}
}
}
Wasn't satisfied with the answers above, although they were the start.
After piecing together some different sources here:
Previous poster in this thread's SO QnA
Code Project Enum Flags Check Post
Great Enum<T> Utility
I created this so let me know what you think.
Parameters:
bool checkZero: tells it to allow 0 as a flag value. By default input = 0 returns empty.
bool checkFlags: tells it to check whether the Enum is decorated w/ the [Flags] attribute.
PS. I don't have time right now to figure out the checkCombinators = false alg which will force it to ignore any enum values which are combinations of bits.
public static IEnumerable<TEnum> GetFlags<TEnum>(this TEnum input, bool checkZero = false, bool checkFlags = true, bool checkCombinators = true)
{
Type enumType = typeof(TEnum);
if (!enumType.IsEnum)
yield break;
ulong setBits = Convert.ToUInt64(input);
// if no flags are set, return empty
if (!checkZero && (0 == setBits))
yield break;
// if it's not a flag enum, return empty
if (checkFlags && !input.GetType().IsDefined(typeof(FlagsAttribute), false))
yield break;
if (checkCombinators)
{
// check each enum value mask if it is in input bits
foreach (TEnum value in Enum<TEnum>.GetValues())
{
ulong valMask = Convert.ToUInt64(value);
if ((setBits & valMask) == valMask)
yield return value;
}
}
else
{
// check each enum value mask if it is in input bits
foreach (TEnum value in Enum <TEnum>.GetValues())
{
ulong valMask = Convert.ToUInt64(value);
if ((setBits & valMask) == valMask)
yield return value;
}
}
}
This makes use of the Helper Class Enum<T> found here that I updated to use yield return for GetValues:
public static class Enum<TEnum>
{
public static TEnum Parse(string value)
{
return (TEnum)Enum.Parse(typeof(TEnum), value);
}
public static IEnumerable<TEnum> GetValues()
{
foreach (object value in Enum.GetValues(typeof(TEnum)))
yield return ((TEnum)value);
}
}
Finally, here's a example of using it:
private List<CountType> GetCountTypes(CountType countTypes)
{
List<CountType> cts = new List<CountType>();
foreach (var ct in countTypes.GetFlags())
cts.Add(ct);
return cts;
}
What I did was change my approach, instead of typing the input parameter of the method as the enum type, I typed it as an array of the enum type (MyEnum[] myEnums), this way I just iterate through the array with a switch statement inside the loop.
Here's yet another C# 7.3 solution using Linq
using System;
using System.Collections.Generic;
using System.Linq;
public static class FlagEnumExtensions
{
public static IEnumerable<T> GetFlags<T>(this T en) where T : struct, Enum
{
return Enum.GetValues<T>().Where(member => en.HasFlag(member)).ToArray();
}
}
Edit: added .ToArray() to prevent multiple enumerations.
You dont need to iterate all values. just check your specific flags like so:
if((myVar & FlagsEnum.Flag1) == FlagsEnum.Flag1)
{
//do something...
}
or (as pstrjds said in comments) you can check for use it like:
if(myVar.HasFlag(FlagsEnum.Flag1))
{
//do something...
}
Building upon Greg's answer above, this also takes care of the case where you have a value 0 in your enum, such as None = 0. In which case, it should not iterate over that value.
public static IEnumerable<Enum> ToEnumerable(this Enum input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
if (input.HasFlag(value) && Convert.ToInt64(value) != 0)
yield return value;
}
Would anyone know how to improve upon this even further so that it can handle the case where all flags in the enum are set in a super smart way that could handle all underlying enum type and the case of All = ~0 and All = EnumValue1 | EnumValue2 | EnumValue3 | ...
You can use an Iterator from the Enum. Starting from the MSDN code:
public class DaysOfTheWeek : System.Collections.IEnumerable
{
int[] dayflag = { 1, 2, 4, 8, 16, 32, 64 };
string[] days = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
public string value { get; set; }
public System.Collections.IEnumerator GetEnumerator()
{
for (int i = 0; i < days.Length; i++)
{
if value >> i & 1 == dayflag[i] {
yield return days[i];
}
}
}
}
It's not tested, so if I made a mistake feel free to call me out. (obviously it's not re-entrant.) You'd have to assign value beforehand, or break it out into another function that uses enum.dayflag and enum.days. You might be able to go somewhere with the outline.
All the answers work well with simple flags, you're probably going to get into issues when flags are combined.
[Flags]
enum Food
{
None=0
Bread=1,
Pasta=2,
Apples=4,
Banana=8,
WithGluten=Bread|Pasta,
Fruits = Apples | Banana,
}
probably need to add a check to test if the enum value it self is a combination.
You'd probably need something like posted here by Henk van Boeijen
to cover your requirement (you need to scroll down a bit)
When it comes to performance, which is important in game development, all solutions given are terrible because of garbage allocation and slow speed. This is a garbage free, over 100 times faster solution than accepted answer.
[Flags]
public enum PersonalTraits : short
{
None = 1 << 0,
Strength = 1 << 1,
Agility = 1 << 2,
Attack = 1 << 3,
Defence = 1 << 4,
Vitality = 1 << 5,
Stamina = 1 << 6,
Accuracy = 1 << 7,
Perception = 1 << 8,
Charisma = 1 << 9,
}
PersonalTraits athlete = PersonalTraits.Stamina | PersonalTraits.Strength;
for (short i = 0, value = 0; value <= (short)PersonalTraits.Charisma; i++, value = (short)(1 << i))
if (((short)athlete & value) != 0)
yield return (PersonalTraits)value;
It could be aswell as the following code:
public static string GetEnumString(MyEnum inEnumValue)
{
StringBuilder sb = new StringBuilder();
foreach (MyEnum e in Enum.GetValues(typeof(MyEnum )))
{
if ((e & inEnumValue) != 0)
{
sb.Append(e.ToString());
sb.Append(", ");
}
}
return sb.ToString().Trim().TrimEnd(',');
}
It goes inside if only when the enum value is contained on the value
You can do it directly by converting to int but you will loose type checking.
I think the best way is use something similar to my proposition. It keep the proper type all the way. No conversion required. It is not perfect due to boxing which will add a little hit in performance.
Not perfect (boxing), but it does the job with no warning...
/// <summary>
/// Return an enumerators of input flag(s)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static IEnumerable<T> GetFlags<T>(this T input)
{
foreach (Enum value in Enum.GetValues(input.GetType()))
{
if ((int) (object) value != 0) // Just in case somebody has defined an enum with 0.
{
if (((Enum) (object) input).HasFlag(value))
yield return (T) (object) value;
}
}
}
Usage:
FileAttributes att = FileAttributes.Normal | FileAttributes.Compressed;
foreach (FileAttributes fa in att.GetFlags())
{
...
}
In C#, can you use number ranges in enum types, for example
public enum BookType
{
Novel = 1,
Journal = 2,
Reference = 3,
TextBook = 4 .. 10
}
EDIT: The reason this is needed is to cast from a number to the enum type, eg:
int iBook = 5
BookType btBook = (BookType)ibook
Debug.Print "Book " + ibook + " is a " btBook
and the expected output is: Book 5 is a TextBook
As others have said, no it isn't possible. It is possible to combine enum values if they are flags:
[Flags]
public enum BookType
{
Novel = 0,
Journal = 1 << 0,
Reference = 1 << 1,
TextBook1 = 1 << 2,
TextBook2 = 1 << 3,
TextBook3 = 1 << 4,
TextBook4 = 1 << 5,
TextBook5 = 1 << 6,
TextBooks1To5 = TextBook1 | TextBook2 | TextBook3 | TextBook4 | TextBook5
}
According to the C# standard (p612, The C# Programming Language) the value given to an enumeration must be a constant integer (or any similar type - long, byte, sbyte, short, etc), so a range of values isn't valid.
My compiler (VS2008) agrees with the spec.
Since you can't repeat names within an enumeration, the closest you'll get is something like this:
public enum BookType
{
Novel = 1,
Journal = 2,
Reference = 3,
TextBook4 = 4,
TextBook5 = 5, ...
TextBook10 = 10
}
Which is actually pretty ugly. Perhaps an enum is not the solution to your particular problem ...
Since you are unable to assign a value range to an enum, I thought of an alternative approach in order to assign an enum as a limit value (the example is based on time):
private enum eTiming
{
eOnTime = 0,
eSlightDelay = 5,
eMinorDelay = 15,
eDelayed = 30,
eMajorDelay = 45,
eSevereDelay = 60
}
private static eTiming CheckIfTimeDelayed(TimeSpan tsTime)
{
eTiming etiming = eTiming.eOnTime;
foreach (eTiming eT in Enum.GetValues(typeof(eTiming)))
{
if (Convert.ToInt16(eT) <= tsTime.TotalMinutes)
etiming = eT;
}
return etiming;
}
This is assuming that the enum is sorted, and works unexpectedly with signed (-) values.
Somewhat offtopic, you can simulate enums using normal classes with readonly fields.
e.g. something similair to this would solve your problem:
public sealed class BookType
{
public static readonly BookType Novel = new BookType(1, 1, "Novel");
public static readonly BookType Journal = new BookType(2, 2, "Journal");
public static readonly BookType Reference = new BookType(3, 3, "Reference");
public static readonly BookType Textbook = new BookType(4, 10, "Textbook");
public int Low { get; private set; }
public int High { get; private set; }
private string name;
private static class BookTypeLookup
{
public static readonly Dictionary<int, BookType> lookup = new Dictionary<int, BookType>();
}
private BookType(int low, int high, string name)
{
this.Low = low;
this.High = high;
this.name = name;
for (int i = low; i <= high; i++)
BookTypeLookup.lookup.Add(i, this);
}
public override string ToString()
{
return name;
}
public static implicit operator BookType(int value)
{
BookType result = null;
if (BookTypeLookup.lookup.TryGetValue(value, out result))
return result;
throw new ArgumentOutOfRangeException("BookType not found");
}
}
It's quite a bit more verbose than a normal enum, but it does allow you to define ranged members in an enum like manner.
e.g.
var bookType = (BookType)5;
Console.WriteLine(bookType);
If you can assign the values to enum-strings yourself then you can use some bitmagic to map multiple int values to same enum value. Subtypes could be enums themselves for every BookType (NovelTypes, JournalTypes, etc).
On the downside
it does require some value modification when casting to BookType
every subtype range is of the same size (16 in current example.
it is a bit less readable than simple Novel = 3 kind of mapping.
Example code:
class Program
{
/// <summary> Number of subtypes reserved for each BookType. </summary>
private const byte BookTypeStep = 16;
/// <summary> Bitmask to use to extract BookType from a byte. </summary>
private const byte BookTypeExtractor = Byte.MaxValue - BookTypeStep + 1;
/// <summary> Bitmask to use to extract Book subtype from a byte. </summary>
private const byte BookSubTypeExtractor = BookTypeStep -1;
public enum BookType : byte
{
Unknown = 0,
Novel = BookTypeStep * 1,
Journal = BookTypeStep * 2,
Reference = BookTypeStep * 3,
TextBook = BookTypeStep * 4,
}
static void Main(string[] args)
{
for(int i = 16; i < 80; i++)
{
Console.WriteLine("{0}\tof type {1} ({2}),\tsubtype nr {3}",
i,
i & BookTypeExtractor,
(BookType)(i & BookTypeExtractor),
i & BookSubTypeExtractor
);
}
Console.ReadLine();
}
}
This example has ranges 16-31 for Novels, 32-47 for journals, etc.
No, it's not. If the numeric constants you're trying to map to truly have the same meaning, you would still need a separate member for each numeric constant. Like TextBook4, TextBook5, etc.
You can opt for a dictionary rather.
var BookType = new Dictionary<int, string>();
BookType.Add(1, "Novel");
BookType.Add(2, "Journal");
BookType.Add(3, "Reference");
BookType.Add(4, "TextBook");
BookType.Add(5, "TextBook");
BookType.Add(6, "TextBook");
BookType.Add(7, "TextBook");
BookType.Add(8, "TextBook");
BookType.Add(9, "TextBook");
BookType.Add(10, "TextBook");
int iBook = 5
Debug.Print "Book " + iBook + " is a " BookType[iBook]
Edit: You can also declare your dictionary readonly if it's in class level.
You can use an enum as the Dictionary value instead of string.
Perhaps you meant to ask a related question, which is: can you have more than one enumeration (not sure I have the terminology correct, but my example will show what I mean) for each value?
In C#, you can do something like this:
public enum BookType
{
Novel = 1,
Journal = 2,
Magazine = 2,
Reference = 3,
TextBook = 4,
LabWorkbook = 4,
Dictionary = 5,
Encyclopedia = 5
}
This way, you can use either BookType.Journal or BookType.Magazine in your code, either of which is synonymous with the value 2. Whether this should be done is another matter - I'm not familiar with the arguments for or against this (I'd like to say "if C# allows it, it must be OK", but that would be utterly crazy).
The simplest answer to your question is No. The easiest way to accomplish what you desire is:
public enum BookType
{
Novel = 1,
Journal = 2,
Reference = 3,
TextBook = 4
}
public void bookOutput(int book)
{
if(book < 4)
Console.Writeline("Book "+book+" is a " + ((BookType)book).ToString());
else
Console.Writeline("Book "+book+" is a " + BookType.TextBook.ToString());
}
The idea is to let enum be individual values and handle the range with logic statements.