0

this is my setup:

public class MyEnums { [Flags] public enum MyGroups { None = 0, Test1 = 1, Test2 = 2 } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public sealed class MyAttribute : AuthorizeAttribute { private readonly MyGroups _allowedGroups; public MyAttribute(MyGroups allowedGroups) { _allowedGroups = allowedGroups; } ... } [MyAttribute(MyGroups.Test1 | MyGroups.Test2)] public class MyController : Controller { ... } 

I specifically do not understand what is happening in the [MyAttribute(MyGroups.Test1 | MyGroups.Test2)] part on the controller side. Am I instantiating multiple attributes (?)"

[MyAttribute(MyGroups.Test1)] [MyAttribute(MyGroups.Test2)] 

Thanks in advance!

4
  • 1
    This is what's called a flag enum and it's "used whenever the enum represents a collection of possible values rather an a single value" from this excellent Q&A. It basically allows you signal to a user that the values in the enum can appear in any grouping. The AttributeUsage is an excellent example. In your code it specifies that MyAttribute is valid on Classes and Methods Commented Jul 16, 2020 at 8:50
  • There’s only one attribute so there’s no instantiating multiple attributes Commented Jul 16, 2020 at 8:52
  • 1
    As MindSwipe has mentioned, you have only one attribute, but its value can be a mix of MyGroups enum. in your [MyAttribute(MyGroups.Test1 | MyGroups.Test2)] the value of allowedGroups would be 3 (both MyGroups.Test1 and MyGroups.Test2) Commented Jul 16, 2020 at 8:56
  • Totally clear, thanks everyone! I thought it had to do with the attribute in my controller itself while instead it had to do with [Flag] attribute. Thanks again!:) Commented Jul 16, 2020 at 9:00

1 Answer 1

1

| is the bitwise OR operator.

You are not defining 2 attributes, you are defining 1, and passing an enum that has the value Test1 or Test2.

It might be clearer if you define your enum using binary literals:

[Flags] public enum MyGroups { None = 0b0000, // 0000 Test1 = 0b0001, // 0001 Test2 = 0b0010 // 0010 } 

When you do a bitwise OR, you check each binary digit, and the result is where 1 is present in either value (as opposed to bitwise AND, which requires both digits to be 1).

So MyGroups.Test1 | MyGroups.Test2 is equivalent to:

 0001 | 0010 = 0011 

When using this technique, it is important to use square numbers for the enum values to ensure that the bitwise operations do not result in a value that clashes with a single enum value. So if you were to extend your enum you should do the following:

[Flags] public enum MyGroups { None = 0b0000, // 0000 Test1 = 0b0001, // 0001 Test2 = 0b0010, // 0010 Test3 = 0b0100, // 0100 Test4 = 0b1000 // 1000 } 

Or using integer literals:

[Flags] public enum MyGroups { None = 0, Test1 = 1, Test2 = 2, Test3 = 4, Test4 = 8 } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.