0

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.

  • How can I get the proper enum value by its long version?
  • How can I switch one value in UserPermissions field by its long representation?

I have tried usersPermissions |= permissionValue but it says I can not use the |= operator on long and Permission Types.

2
  • Does this answer your question? How to remove an item for a OR'd enum? Commented Feb 24, 2020 at 14:15
  • I guess, that you should use & and ~, like it's pointed out in attached duplicate Commented Feb 24, 2020 at 14:17

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

You have to do an exclusive OR operator on the enumeration. So if you permissions value has:

  • Value1
  • Value2
  • Value3
  • Value4,

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;

2 Comments

My problem is that I get a long value instead of Permissions.Value4. That's why bitwise operators don't work this way. How can I say perm = perm ^ (long)valueComingFromClient
Enumeration, in your case, is of type long and that is the type that is being worked with under the hub so you need to do a bit of casting - perm = (Permissions)((long)perm ^ (long)4)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.