In my project i am using an Array of bool which defines the user's access rights.
For example
public bool[] Security {get; set;}
where
[0] = Admin
[1] = GrantWrites
[2] = GrantDeletes
[3] = User
It is working quite well.
I would set it to {F,T,F,T} or {0,1,0,1} and that particular user gets access as a User and it allows him to write.
I am trying to convert it to an enum but apparently i would need an array of it.
currently i have the following (not working)
public class UserCrops
{
public UserCrops(etc.., Enum[] _Security)
{
.
.
.
Security = _Security;
}
.
.
.
public Enum[] Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
}
I found some links like this but no help.
Thanks in advance
Edit: Both answers are very well explained but I am going with the non-Flag one just because it seems easier for me :)
Edit2: How can i create a new object (outside of class?)
I used to do
bool[] security = new bool[9];
for (int i = 0; i < 9; i++)
{
security[i] = chklstSecurity.Items[i].Selected;
}
userCropList.Add(new UserCrops(.., txtBiologicalAssessmentApprovalDate.Text, security));
But now?
Try with:
[Flags]
public enum Security
{
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
And you'll use it like this:
Security security = Security.GrantWrites | Security.GrantDeletes;
if ((security & Security.GrantWrites) == Security.GrantWrites)
{
}
Comparison can be simplified as pointed out by p.s.w.g. to increase its readability. Moreover I suggest to include a default value in the enum (for when variable is not initialized):
[Flags]
public enum Security
{
None = 0,
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
Finally note that you can provider shortcut for common combinations of flags:
[Flags]
public enum Security
{
// Other values
FullAccess = Admin | GrantWrites | GrantDeletes
}
More of that on MSDN. Please note this approach mimics attributes for file/directories in file system (and many other). IMO is much simpler to use than keep an array of enums as suggested in the other answer:
You do not have to search entire array to check if a permission is granted or not.
You do not have to check for a null value (enum can't be null, an array can be).
It uses less space (even if nowadays this is not so important).
It's naturally (more) safe so less checks are needed (for example to avoid duplicates inside array).
It can be easy stored (as text or integer without additional code).
But it has, compared to that, two main drawbacks:
Flags are finite (32 if you're using an Int32 for your enum or 64 for an Int64).
You can't easily switch to something else (if, for example, Security has to become a class you'll need to write much more code to mimic enums syntax and some assumption made by code when working with enums will be broken).
Remove the [] and use enum instead of Enum:
public enum Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
And you probably want to use Security[] as a method parameter:
public UserCrops(etc.., Security[] _Security)
Using flags (as Adriano suggests) is an excellent suggestion too, but it will require you to rethink how you're storing your permissions. Instead of storing an array of bool's, you'll represent the entire security set as a single value, with different bits representing each permission.
Read Enumeration Types (C# Programming Guide) under the section Enumeration Types as Bit Flags for more information.
Related
In C#, i have the following enum. i want to be able to run my verification function an return the issues found via said enum, but it seems to always contain OK.
everything ive read on this says to use 0 for none, which, to me at least, seems logically equivalent to OK, as there are "none" problems.
but if i check "enum.HasFlag(ValidationResult.OK)" it will return true 100% of the time, no matter how many others are set. i feel like if it doesnt equal 0, it shouldnt say it does. this seems broken to me.
What is the proper way to deal with this?
[Flags]
public enum ValidationResult
{
OK,
NotOK,
ReallyNotOk
}
void Main()
{
var x = ValidationResult.OK;
Console.Write(x.HasFlag(ValidationResult.OK)); // true
var y = ValidationResult.NotOk;
Console.Write(y.HasFlag(ValidationResult.OK)); // still true for some reason
}
0 isn't a flag, it is the complete absence of flags. If the flags represent different types of failures, then it may be appropriate to give the label Ok to 0... but it still isn't a flag and cannot be tested with HasFlag.
Console.Write(y == ValidationResult.OK); // works correctly
namespace EnumTest
{
[Flags]
public enum ValidationResult
{
None = 0,
OK = 1,
NotOK = 2,
ReallyNotOk = 4
}
class Program
{
static void Main(string[] args)
{
ValidationResult x = ValidationResult.OK;
Console.Write(x.HasFlag(ValidationResult.OK)); // true
ValidationResult y = ValidationResult.NotOK;
Console.Write(y.HasFlag(ValidationResult.OK)); // Result False
ValidationResult z = ValidationResult.NotOK | ValidationResult.ReallyNotOk;
Console.Write(z.HasFlag(ValidationResult.OK)); // Result False
}
}
}
In addition to the answer of Ben Voigt, you can fix this by adding desired values manually like:
[Flags]
public enum ValidationResult
{
OK = 1,
NotOK = 2,
ReallyNotOk = 4
}
Update:
As Ben pointed out in his comment, the presented solution lacks the possibility to present EITHER "OK" OR a concrete failure state. Thus I would propose using a class hierarchy instead of an enumeration.
A simple example can be found in the microsoft docs:
Use enumeration classes instead of enum types
I have a question that I'm sure has already been answered. Any help pointing me in the right direction would be appreciated.
I have a standard ASP MVC site. As with any site, I have the usual collection of key values for various aspects of the application.
Hair Color
10 = Green
20 = Brown
...
Status
10 = Active
20 = Paused
99 = Inactive
...
SubscriptionType
10 = 1 Week
20 = 1 Month
30 = 3 Month
...
Approval
0 = Pending Approval
10 = Approved
20 = Approved with Conditions
99 = Rejected
etc..etc..etc...
Normally, I have a bunch of DB tables associated with the various types but I find all the overall management of this method tedious (creating, adding values, SQL calls)
My question:
Is there a simple and straightforward way of defining and accessing these key values within the MVC code itself. I know I can use various means (Lists, Dictionary, Hashtables, Enums, etc..) but I'm looking for something that I can easily access across various Controllers AND Views (in some Common Helper class?). I want to be able to get the value from the key OR the reverse and get the key from the value.
I know there are probably 1000 ways to skin this cat but I'd be interested if anyone could point me to a simple and straightforward way to do it. Is this something that could (or should) be done in the Model layer? A Helper "CommonValues" class? Any suggestions would be welcome.
Apologies if this is "Programming 101" stuff. (I'm self taught)
For integers
You can use an enum, like this:
enum SubscriptionType
{
OneWeek = 10,
OneMonth = 20,
ThreeMonths = 30
}
You could certainly define your enums as members of a CommonValues class, if you have one. Or you could define them within the namespace and outside of any class, which would make them globally available.
For strings (or integers if you like this method better)
You can define constants as a member of a class. Constants are exposed as static fields so they are accessible anywhere.
public class CommonValues
{
public const string ColorRed = "RED";
public const string ColorBlue = "BLUE";
public const string WorkflowStateStopped = "STOPPED";
public const string WorkflowStateRunning = "RUNNING";
}
//Main program
var a = CommonValues.ColorRed;
var b = CommonValues.WorkflowStateRunning;
Notice the messy "ColorXXX" pattern. Seems a little 90s to me. If you want to restrict namespaces so your intellisense works a bit more usefully, you can use a nested class.
public class CommonValues
{
public class Colors
{
public const string Red = "RED";
public const string Blue = "BLUE";
}
public class WorkflowStates
{
public const string Running = "RUNNING";
public const string Stopped = "STOPPED";
}
}
//Main program
var b = CommonValues.Colors.Red;
var c = CommonValues.WorkflowStates.Running;
Display
When it comes to display the meaning of one of these codes, naturally your display elements should come from resources, which will automatically adapt to the current culture (after all, some day you will be an international giant). You can organize your resources with names like this:
var resources = new ResourceManager("CommonValues", myAssembly);
//Example for use with enum
SubscriptionType code = SubscriptionType.OneWeek;
var display = resources.GetString("SubscriptionType." + code.ToString()); //Resource ID = "SubscriptionType.OneWeek";
//Example for use with string constant
var colorCode = CommonValues.Colors.Red;
var display = resources.GetString("Colors." + colorCode); //Resource ID = "Colors.Red";
I wanted to put in some details of what I did in case this helps others down the line. Using John Wu's answer from above (thanks!!), here's what I did.
Create the enum. You need to put this in some class that you can reference in the View. I called mine EnumValues in the EnumHelper namespace.
namespace MyProject.EnumHelper
{
public static class EnumValues
{
public enum ProjectStatus
{
Active = 10,
Paused = 20,
Inactive = 99
}
...
So the beginning of my View looks like
#using MyProject.EnumHelper;
#model MyProject.Models.ProjectViewModel;
...
Now, if I have the integer value (say from the DB call) and I want the decoded string (ex. "Active"), I did this in the view.
var projectstatus = (EnumValues.ProjectStatus)Model.project_status;
If I need to get the enum integer value (ex. in a dropdown), I did this in the view.
var projectstatusid = (int)EnumValues.ProjectStatus.Active;
Thanks again to John Wu for pointing me in the right direction.
In my scenario I have a class called Person. I need to test if certain people are compatible or not and return a bool value. I was thinking of using an enum setup to make it easier to test these compatibility tests. However I'm not familiar with enum and was hoping someone could shed some light or help demonstrate how i would use it in my case.
I was thinking it would be easiest to assign an id to each Person and a compatibility list along with that ID. Below is some pseudo code demonstrating what i mean. I'm just not clear on how to to set this up using enums.
ID's assigned to each class object
1 = Person(John)
2 = Person(Kevin)
3 = Person(Michelle)
4 = Person(Krystal)
5 = Person(Leslie)
Compatibility lists
1 = [2,4]
2 = [1,3,5]
3 = [2,5]
4 = [1]
5 = [2,3]
The tests I want to Perform and return a bool value.
If (Person(John) compatible with Person(Krystal))
{return true}else{return false}
Honestly, an enum is not the solution for this. The closest analogy to your "compatibility checker" would probably be an EqualityComparer<T> in .NET. It's a separate class.
The comparison "are two people compatible" really doesn't belong in the Person class. It depends on what measure of compatibility you are comparing them and over time that comparison may change or you may add other compatibility comparers.
So, instead of an enum create a CompatibilityComparer class. For now this has one method .IsCompatible(Person a, Person b) and inside that method you can use a dictionary, database lookup, complex calculation based on weighted values from a and b, or whatever else you want.
private static readonly CompatibilityComparer comparer
= new CompatibilityComparer();
...
if (comparer.IsCompatible(john, krystal)) ...
See separation of concerns and single responsibility principle.
Ideally your comparer would also operate on an interface IPerson rather than the concrete class Person so you can test it more easily with mock IPerson objects.
A simplest example, using a Dictionary of compatible people might be:
Dictionary<int, int[]> matrix = new Dictionary<int, int[]>();
// You could initialize this statically, or better yet, use Lazy<>
static CompatibilityComparer()
{
matrix[1] = new[] { 2, 4 };
...
}
public bool IsCompatible(Person a, Person b)
{
return matrix[a.Id].Contains(b.Id);
}
You could also represent your graph of compatibility as a list of pairs of compatible people ids, as a 2D square matrix, or any other graph representation.
If you really do have all the Person objects in memory, statically defined, it would be better to have a Dictionary<Person, List<Person>> although at some point one has to ask, "what's the real environment here?", it's not an interesting problem until there are thousands of People and they are in a database and then a different approach is needed again.
How was 'compatibility' decided? a) by a person entering data in a database or b) by some algorithm? If the former then that would involve Ids and a 'compatibility' table in the database with two foreign keys back to the people table (like the dictionary is meant to illustrate). And if the latter why isn't that in code?
I would suggest you to use enums together with extension methods. Let me explain how this would work for you.
public enum Person
{
John = 1,
Kevin = 2,
Michelle = 3,
Krystal = 4,
Leslie = 5
}
Here you have identifiers with an associated number set explicitly. However, this number association is optional and can be elided.
public static class PersonExtensions
{
private Dictionary<Person,List<Person>> compatiblePersons = createCompatiblePersons();
private static Dictionary<Person,List<Person>> createCompatiblePersons()
{
var d = new Dictionary<Person,List<Person>>;
// put your compatibilities here
d[Person.John] = new List()
{
Person.Kevin,
Person.Krystal
};
return d;
}
public static List<Person> GetCompatiblePersons(this Person person)
{
return compatiblePersons(person);
}
public static bool IsCompatibleWith(this Person person, Person other)
{
return this.GetCompatiblePersons().Contains(other);
}
}
This static class allows to use extension methods on any Person instance, e.g. Person.John.IsCompatibleWith(Person.Michelle) will return false in this case. The association is made in the Dictionary declared above. This technique allows you to add "properties" to your enums like the ability to ask for compatibility or get the list of compatible persons. However, i would suggest to choose a class if it gets more complex than this.
The answer of #OwlSolo in contrast does the job but is somewhat limited, but if your requirements are just as described I would recommend just adding a convenience extension method, which hides the logical bit calculations and take the [Flags] approach.
Code written blindly, so no warranties for compilation errors
What you want is an enum type with the flags attribute:
[Flags]
enum MyCompatibilities
{
a = 1,
b = 2,
c = 4,
d = 8
}
With this you can assign a number of enum elements that apply.
MYCompatibility comp = MYCompatibility.a | MYCompatibility.b;
| is a logical OR and it means that your variable comp has the properties a as well as b
You can find out whether a certain compatibility is set via bit comparison:
if (comp & MYCompatibility.a= != 0)
or with the logic provided by the [Flags] attribute:
if (comp.HasFlag(MYCompatibility.a))
For the inner workings of this, google for bit flags.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
There has been talk of Enums in general violating Clean Code-principles, so I'm looking for people's favorite Enum anti-patterns and alternative solutions for these.
For example I've seen code like this:
switch(enumValue) {
case myEnum.Value1:
// ...
break;
case myEnum.Value2:
// ...
break;
}
It's one step better than switch-statements with magic strings, but this probably could have been solved better with a factory, a container or other pattern.
Or even old-school code like this:
if(enumValue == myEnum.Value1) {
// ...
} else if (enumValue == myEnum.Value2) {
// ...
}
What other anti-patterns and better implementations have you experienced with enums?
I think Enums are quite useful. I've written a few extensions for Enum that have added even more value to its use
First, there's the Description extension method
public static class EnumExtensions
{
public static string Description(this Enum value)
{
var entries = value.ToString().Split(ENUM_SEPERATOR_CHARACTER);
var description = new string[entries.Length];
for (var i = 0; i < entries.Length; i++)
{
var fieldInfo = value.GetType().GetField(entries[i].Trim());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
}
return String.Join(", ", description);
}
private const char ENUM_SEPERATOR_CHARACTER = ',';
}
This will allow me to define en enum like this:
public enum MeasurementUnitType
{
[Description("px")]
Pixels = 0,
[Description("em")]
Em = 1,
[Description("%")]
Percent = 2,
[Description("pt")]
Points = 3
}
And get the label by doing this: var myLabel = rectangle.widthunit.Description() (eliminating any need for a switch statement).
This will btw return "px" if rectangle.widthunit = MeasurementUnitType.Pixels or it will return "px,em" if rectangle.widthunit = MeasurementUnitType.Pixels | MeasurementUnitType.Em.
Then, there is a
public static IEnumerable<int> GetIntBasedEnumMembers(Type #enum)
{
foreach (FieldInfo fi in #enum.GetFields(BindingFlags.Public | BindingFlags.Static))
yield return (int)fi.GetRawConstantValue();
}
Which will let me traverse any enum with int based values and return the int values themselves.
I find these to be very useful in an allready useful concept.
It all depends what your trying to do with the enum.
If you are trying to stop your developers from passing magic numbers into your operations and you want to keep the data referential integrity intact with your DB then, YES! Use T4-Templates (using your ORM) to go to your MeasurementUnitTypes table and generate a enum with the ID, Name and Description columns matching the enum’ int, Enum_Name and Description Attribute (nice approach for additional field\data to enum #danijels) as suggested above. If you add a new Measurement Type to your MeasurementUnitTypes table you can just right click and run the T4-Template and the enum code is generated for that new row added in the table. I don’t like hard-coded data in my application that doesnt link to my DB hence the mention of the T4-Template approach. It is not extensible otherwise...what if some other external system wants to retrieve our Measurement Criteria used in our system, then it is hard-coded in the system and you can't expose it to the client via a service. That left there.
If the purpose is not data related and you have some logic assigned to a specific enum then NO! this violates the SOLID (Open close principle) as you would somewhere in your application apply a switch or bunch of Ifs to action the logic per enum, ALSO if you did it REALLY bad these switches or Ifs are all over the show....good luck adding a new enum... so it is not open for extension and closed for modification as you need to modify existing code, as per the SOLID principle.
If your choice is 2 then I suggest then to replace your enum with the following using the example from #danijels comment:
public interface IMeasurementUnitType
{
int ID { get; }
string Description { get; }
// Just added to simulate a action needed in the system
string GetPrintMessage(int size);
}
The above code defines the interface (code contract) that each measurement should adhere to. Now lets define Percentage and Pixel measurement :
public class PixelsMeasurementUnitType : IMeasurementUnitType
{
public int ID => 1;
public string Description => "Pixel";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} pixels of the total screen size";
}
}
public class PercentMeasurementUnitType : IMeasurementUnitType
{
public int ID => 2;
public string Description => "Persentage";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} persent of total screen size (100)";
}
}
So wee have defined two types, we would use them in code as follows:
var listOfMeasurmentTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IMeasurementUnitType).IsAssignableFrom(p)
&& !p.IsInterface)
.ToList();
Here we grab all the TYPES that extends the IMeasurementUnitType interface and NOT the interface itself. Now we can use the Activator to create instances of the classes to populate our UI controls:
public IEnumerable<IMeasurementUnitType> GetInstantiatedClassesFromTypes(List<Type> types)
{
foreach (var type in types)
{
yield return (IMeasurementUnitType)Activator.CreateInstance(type);
}
}
You can change the code above to be generic for any type, AND NOW life happens and the client give a new measuring unit type called Point as a new requirement, I don't need to CHANGE ANY code, just add the new type (extend the code NOT modify). The new type will automatically be picked up in the application.
public class PointMeasurementUnitType : IMeasurementUnitType
{
public int ID => 3;
public string Description => "Point";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} points of total screen size";
}
}
a Good idea would be to cache your types for performance benefits upon starting your application or try and use a DI container of your choice.
Also, one can argue that somewhere in you application you would need to distinguish between types and I agree, however you want to keep apples with apples. So try as far as possible to apply the same principle used for this types. If this type is used in some sort of Graphics processor (for example) class then have a IGraphicsProcessor and have your concrete classes that differentiate between these types for example PersentageAndPixelGraphicsProcessor (that extends from IGraphicsProcessor) or if it distinguishes only one type call it PersentageGraphicsProcessor.
Sorry for the HUGE SA but I really like enum's however I feel when you trying to separate logic using a enums it is a STRONG anti-pattern.
comments welcome,
This isn't an answer, as much as contributing to a list of Enum anti-patterns.
During a code review this morning, I ran into a case similar to the following, all in the same class.
Two cases:
Before drinking
After drinking
..
public enum ListEnum
{
CategoryOne,
CategoryTwo,
CategoryThree,
CategoryFour
}
public class UIELementType
{
public const string FactoryDomain = "FactoryDomain";
public const string Attributes = "Attributes";
}
Using enums in not anti-pattern. In some books about refactoring this code is used to demonstrate how to replace it with polymorphism. It would be OK when you overuse enums in code.
I see having two switch statements as a symptom of non-OO design as explained further in this answer.
I'm trying to create an authorization scheme for my ASP.NET MVC application where an Enum is used to set permissions. For example:
[Flags]
enum Permissions
{
ReadAppointments = 1,
WriteAppointments = 2 | ReadAppointments,
ReadPatients = 4,
WritePatients = 8 | ReadPatients,
ReadInvoices = 16,
WriteInvoices = 32 | ReadInvoices
...
}
But I don't really like that because it really doesn't make it clear that Write always includes Read.
I then realized that a requirement would be that a user might have NO access to, for example, Appointments.
Essentially, I'd want a "bitfield" with 3 states: none, readonly, full (read/write). I'd like to still use an enum bitfield since it's easy to store in a DB (as an int). Also it's very easy to see if a permission is set.
Does anyone have any idea how this could be easily accomplished using an Enum... or am I going in the completely wrong direction?
EDIT: I'm really trying to avoid storing permission definitions in the DB since I really want things to be changeable without having to modify much on the DB end. It'd be really nice to know how a large scale application would do this.
I would probably do this as separate fields for each area (Invoices. Patients, Appointments) using a single enum to cover each of them.
enum Permission { None, ReadOnly, ReadWrite };
To me, this is easier to understand and manage, and it doesn't combine a bunch of unrelated things (I should say "seemingly unrelated", since I don't know anything about your app).
wouldn't a value of 0 mean no permissions? ie:
0 is cannot modify appointments, patients, or invoices
1 is read appointments, but cannot modify others
2 is write appointments, but cannot modify others
3 is read/write appointments, but cannot modify others
4 is read patients, but cannot modify others.
so if you have...
51 that's:
read/write invoices and read/write appointments, but no access to patients...
Strictly speaking, you can't have a bitfield with anything other than two possible values any more than you can have a single (decimal) numeric digit with more than ten possible values. Base 2 means two values.
With that out of the way, don't store business-specific permissions as binary values; you will regret it later. Store them individually. Feel free to use a bitfield for defining the specifics of the permission (none/read/write/etc.), but not the nature of the permission itself.
Why is this Community Wiki?
I borrowed and modified this example from: C# vs Java Enum (for those new to C#)
Regardless I would not use an enum, I would use a class which would allow for much more flexibility. Something like this may help, just don't add patients and invoices as that varies orthogonally from the issue of read and write permissions.
There are many ways to do the bit manipulations and that should probably be done on a separate layer of code. If you need bit manipulations for serialization (to a file or database) then you should put that code there.
I don't use C# much so the syntax may be off, I do Java mostly. Anyway, the basic concept should be clear here:
public class Permissions
{
public static readonly Permissions NONE = new PERMISSIONS("NONE",false,false);
public static readonly Permissions READ = new PERMISSIONS("READ",true,false);
public static readonly Permissions FULL= new PERMISSIONS("FULL",true,true);
public static IEnumerable<Permissions> Values
{
get
{
yield return NONE;
yield return READ;
yield return FULL;
}
}
private readonly string name;
private readonly boolean read;
private readonly boolean write;
private readonly int bits;
Permissions(string name, boolean read,boolean write)
{
this.name = name;
this.read = read;
this.write= write;
this.bits = bits;
}
public string Name { get { return name; } }
// returns true if read permission is granted
public double isReadable { get { return read; } }
// returns true if write permission is granted
public double isWriteable { get { return write; } }
public override string ToString()
{
return name;
}
// returns bit field
public int bits { get { return write ? 1 : 0 | read ? 2 : 0; } }
}
Wrong direction. Your application will grow, then the bitfield will not be sufficient anymore and you are in for a lot of rework. Better get "proper" from the beginning.