Reputation: 2827
I have a Flags enum
and would like to toggle some values by its (long
) value.
[Flags]
public enum Permissions : long
{
Value0 = 0,
Value1 = 0x1,
Value2 = 0x2,
Value3 = 0x4,
//etc
}
I store the actual permission in the database by EF
using a long
field, eg:
public Permissions UsersPermissions { get; set; }
From the client side I get values one by one to toggle the proper value by enum
, so if the database field contains
`Value1 | Value2 | Value3`
and I get a 4 I have to remove Value3 from the user's permissions.
enum
value by its long version?I have tried usersPermissions |= permissionValue
but it says I can not use the |=
operator on long
and Permission
Types.
Upvotes: 0
Views: 1428
Reputation: 7010
From what I can tell, your input is a number, and you want it to be a Permissions
. Well you can literally cast it, even if it's not one of the discrete values. That will even "just figure out" if it's a combination of one of the flag values. C# enumerations are pretty smart with their casts that way.
Here's a sampling of code to do what you want
[Flags]
public enum TestEnum : long
{
ValueNone = 0, // You can't really "have" a Value0, it's an absence of values
Value1 = 0x1,
Value2 = 0x2,
Value3 = 0x4,
Value4 = 0x8
}
foreach(var enumVal in Enum.GetValues(typeof(TestEnum)))
{
Console.WriteLine("val is: {0} long is: {1}", enumVal, (long)enumVal);
}
{
Console.WriteLine("Start with 1 and 3, remove 3 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value3;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = 4; // TestEnum.Value3
var removeEnum = (TestEnum)testVal;
removeEnum = ~removeEnum;
testEnum &= removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
{
Console.WriteLine("Start with 1, 2, 4 and remove 1 and 4 from number");
var testEnum = TestEnum.Value1 | TestEnum.Value2 | TestEnum.Value4;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
long testVal = (long)TestEnum.Value1 | (long)TestEnum.Value4; // Could also have added them
var removeEnum = (TestEnum)testVal;
Console.WriteLine("Removing: {0}({1})", removeEnum, (long)removeEnum);
testEnum &= ~removeEnum;
Console.WriteLine("testEnum is: {0}({1})", testEnum, (long)testEnum);
}
Here's a way to get the limit of your enum by the value of the last element:
{
// Check the value to see what the range of the enumeration is
var lastVal = Enum.GetValues(typeof(TestEnum)).Cast<TestEnum>().Last();
long limit = (long)lastVal * 2;
Console.WriteLine("Limit of flags for TestEnum is: " + limit);
Func<long, bool> testLambda = x => x < limit;
Console.WriteLine("Value of {0} within limit: {1}", 14, testLambda(14));
Console.WriteLine("Value of {0} within limit: {1}", 16, testLambda(16));
Console.WriteLine("Value of {0} within limit: {1}", 200, testLambda(200));
Console.WriteLine("Value of {0} within limit: {1}", 0, testLambda(0));
Console.WriteLine("Out of range looks like: " + (TestEnum)17);
Console.WriteLine("In range looks like: " + (TestEnum)14);
}
Output:
val is: ValueNone long is: 0
val is: Value1 long is: 1
val is: Value2 long is: 2
val is: Value3 long is: 4
val is: Value4 long is: 8
Start with 1 and 3, remove 3 from number
testEnum is: Value1, Value3(5)
testEnum is: Value1(1)
Start with 1, 2, 4 and remove 1 and 4 from number
testEnum is: Value1, Value2, Value4(11)
Removing: Value1, Value4(9)
testEnum is: Value2(2)
Limit of flags for TestEnum is: 16
Value of 14 within limit: True
Value of 16 within limit: False
Value of 200 within limit: False
Value of 0 within limit: True
Out of range looks like: 17
In range looks like: Value2, Value3, Value4
I'll fully admit there may be a better way of doing above, but fundamentally, if you have a [Flags]
enum, and thus everything inside it is "valid" to a degree (all combinations fine), just check to see if your value is out of range, and then cast it from the integer type directly to the enum type and call it a day. Once it's your flag type, you CAN use the bitwise operators no problem, so just do that first.
Upvotes: 1
Reputation: 109557
You have to do some casting to long
and Permissions
at the appropriate points, like so:
Permissions perms = Permissions.Value1 | Permissions.Value2 | Permissions.Value3;
Console.WriteLine(perms); // Value1, Value2, Value3
long toRemove = 4;
// OR: long toRemove = (long) Permissions.Value3;
perms = (Permissions) ((long)perms & ~toRemove); // Use "& ~X" to remove bits set in X.
Console.WriteLine(perms); // Value1, Value2
The important thing here is that ~toRemove
returns the bitwise complement of toRemove
which thus gives you a set of bitflags that you can &
with the original value in order to turn off all the bits that were set in toRemove
.
You have to cast perms
to long
in order to do this &
operation.
Finally, having got the result you need via &
you have a long
that you must cast back to Permissions
to get the correct enum type as the final answer.
Upvotes: 1
Reputation: 2523
You have to do an exclusive OR operator on the enumeration. So if you permissions value has:
and you want to remove Value4 you will have to do this:
var perm = Permissions.Value1 | Permissions.Value2 | Permissions.Value3 | Permissions.Value4;
perm = perm ^ Permissions.Value4;
Upvotes: 0