admin管理员组文章数量:1122846
I'm finding a way to do sth like this in C#:
// giving eTankComponents is an [Flags] enum
[Flags]
public enum eTankComponents
{
Empty = 0,
Barrel = 1,
wheels = 2,
}
Type enumType = Type.GetType("eTankComponents");
object emptyTank = Enum.Parse(enumType, "Empty");
object tankWithBarrel = Enum.AddFlag(emptyTank, enumType, Enum.Parse(enumType, "Barrel"));
object fullTank = Enum.AddFlag(tankWithBarrel, enumType, Enum.Parse(enumType, "wheels"));`
Is there any Method in c# to do sth like Enum.AddFlag
searched online and found nothing.
I'm finding a way to do sth like this in C#:
// giving eTankComponents is an [Flags] enum
[Flags]
public enum eTankComponents
{
Empty = 0,
Barrel = 1,
wheels = 2,
}
Type enumType = Type.GetType("eTankComponents");
object emptyTank = Enum.Parse(enumType, "Empty");
object tankWithBarrel = Enum.AddFlag(emptyTank, enumType, Enum.Parse(enumType, "Barrel"));
object fullTank = Enum.AddFlag(tankWithBarrel, enumType, Enum.Parse(enumType, "wheels"));`
Is there any Method in c# to do sth like Enum.AddFlag
searched online and found nothing.
Share Improve this question edited Nov 22, 2024 at 15:55 gunr2171 17.4k26 gold badges66 silver badges100 bronze badges asked Nov 22, 2024 at 15:52 216 dark216 dark 31 bronze badge 4 |3 Answers
Reset to default 1Sure, it's called a bitwise OR operation, or |
:
var emptyTank = (eTankComponents)Enum.Parse(enumType, "Empty");
Console.WriteLine(emptyTank); // Empty
var tankWithBarrel = emptyTank | (eTankComponents)Enum.Parse(enumType, "Barrel");
Console.WriteLine(tankWithBarrel); // Barrel
var fullTank = tankWithBarrel | (eTankComponents)Enum.Parse(enumType, "wheels");
Console.WriteLine(fullTank); // Barrel, Wheels
There are many ways of writing the above, from reflection cast to proper types (like my example), to reflection cast to int
(if you don't know the enum type statically), to dynamic
code even.
You can get the underlying values using Convert.ToInt64
and use bitwise OR on them. Int64
is the largest underlying value type that an enum can have, and this will work for enums with smaller underlying value types too.
Then you can use ToObject
to get the enum value from the underlying value.
Type enumType = Type.GetType("eTankComponents");
var barrel = Enum.Parse(enumType, "Barrel");
var wheels = Enum.Parse(enumType, "Wheels");
var combined = Convert.ToInt64(barrel) | Convert.ToInt64(wheels);
Console.WriteLine(Enum.ToObject(enumType, combined));
In .NET 7, I think you can come up with something like this:
public static class EnumExt {
private static ConcurrentDictionary<Type, MethodInfo> s_dict = new();
private static MethodInfo s_orEnumsMethodInfo = typeof(EnumExt)
.GetMethod(nameof(OrEnums), BindingFlags.Static | BindingFlags.NonPublic);
// Unknown type at compile time
public static object AddFlag(Type type, object enumVal, object flagToAdd) {
try {
var methodInfo = s_dict.GetOrAdd(type,ValueFactory);
return methodInfo.Invoke(null, [enumVal, flagToAdd]);
} catch (Exception ex) {
// TODO: make reflection exception more telling
throw;
}
}
public static T AddFlag<T>(this T enumVal, T flagToAdd)
where T : Enum {
return Enum.GetUnderlyingType(typeof(T)) switch {
Type t when t == typeof(byte) => OrEnums<T, byte>(enumVal, flagToAdd),
Type t when t == typeof(sbyte) => OrEnums<T, sbyte>(enumVal, flagToAdd),
Type t when t == typeof(short) => OrEnums<T, short>(enumVal, flagToAdd),
Type t when t == typeof(ushort) => OrEnums<T, ushort>(enumVal, flagToAdd),
Type t when t == typeof(int) => OrEnums<T, int>(enumVal, flagToAdd),
Type t when t == typeof(uint) => OrEnums<T, uint>(enumVal, flagToAdd),
Type t when t == typeof(long) => OrEnums<T, long>(enumVal, flagToAdd),
Type t when t == typeof(ulong) => OrEnums<T, ulong>(enumVal, flagToAdd),
_ => throw new ArgumentException($"Unsupported underlying type {Enum.GetUnderlyingType(typeof(T)).Name}")
};
}
private static MethodInfo ValueFactory(Type t) {
var genMethod = s_orEnumsMethodInfo.MakeGenericMethod(t, Enum.GetUnderlyingType(t));
return genMethod;
}
private static TEnum OrEnums<TEnum, TUnderlying>(TEnum val1, TEnum val2)
where TUnderlying : IBitwiseOperators<TUnderlying, TUnderlying, TUnderlying> {
var firstCast = Unsafe.As<TEnum, TUnderlying>(ref val1);
var secondCast = Unsafe.As<TEnum, TUnderlying>(ref val2);
var result = firstCast | secondCast;
return Unsafe.As<TUnderlying, TEnum>(ref result);
}
}
本文标签: cIs there a way to Add Flag enum to each other without knowing the exact enum typeStack Overflow
版权声明:本文标题:c# - Is there a way to Add Flag enum to each other without knowing the exact enum type? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736302549a1931575.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Enum.Parse(enumType, "Barrel, wheels")
will give you the combined value. But it's not clear to me why you'd need to do that. Are you trying to use reflection to update an object of an unknown type? – Richard Deeming Commented Nov 22, 2024 at 16:01