Currently I have 4 permissions in my website
Edit
Delete
Add
View
Everyone gets view permissions when someone subscribes to someone else.
Currently in I store each as a column in my database as a bit value.
I am thinking maybe I should use enum with flags but I have some questions.
The user will be able to choose the users permissions(eveyone gets view you cannot take that away). Right now it is easy as I use a checkbox and then save the bool value to the db.
My questions is what is the best way to convert checkboxes to the enum type? So if they choose add permission I can map that to the right enum type.
Wondering if there is a better way then
PermissionTypes t;
if(add == true)
{
t = PermissionTypes.Add
}
if(edit == true)
{
t += PermissionTypes.Edit // not sure if you even can do this.
}
I know with enum flags you can use the pipe and do something like this
PermissionTypes t = PermissionTypes.Add | PermissionTypes.Edit
I am wondering is it good practice to have another type in my enum like
AddEdit = Add | Edit
I am thinking that can result in many combinations(imagine if I had like 10 permissions or something like that).
Enums are simply integers values. By settings your enum values to different power of 2, you can easily have any combination you need:
enum ePermissions
{
None = 0,
View = 1,
Edit = 2,
Delete = 4,
Add = 8,
All = 15
}
ePermissions t;
t = (ePermissions)((add?ePermissions.Add:ePermissions.None) | (delete?ePermissions.Delete:ePermissions.None) | ...);
if you want to know if some user has the Add permission just do as follow:
canAdd = (currentPermission & ePermissions.Add) != 0;
On converting set of bool values to enum - for small set if would be ok. You can also use ?: operator to do the same in smaller number of lines:
[Flags]
enum Permissions
{
None = 0,
View = 1,
Edit = 2,
Delete = 4,
Add = 8,
}
var permissions =
(add ? Permissions.Add : Permissions.None) |
(edit ? Permissions.Edit : Permissions.None) |
(delete ? Permissions.Delete : Permissions.None);
If you have large number of values some sort of mapping of Control to Enum may be useful.
On AddEdit - this particular on is probably not useful. You can as easily write Add | Edit. Some menaingful combinations of permissions (or falgs) may be named specifically if code will use such combination in meanigfull way. I.e. CanModify = Add | View.
Related
I am having a small problem, and I cant seem to find an answer anywhere. I will try to keep it short and clear
I have a class called exercises, which has an enum responsible for what body parts the exercise hits. Lets say we have
Chest = 1
Shoulders = 2
Arms = 4
Legs = 8
Back = 16
So far my class "exercise" has a name, and this enum. In theory, this should result in having something like "Bech press - chest, arms n/ Deadlift - back, legs" and so on.
Next I have a class Catalog, that holds all the exercises, and in that class a method, called AddExercise. Here is the code snippet:
public void AddExercise()
{
Exercise ToAdd = new Exercise();
Console.WriteLine("What is the name of the exercise?");
string name = Console.ReadLine();
ToAdd.name = name;
katalog.Add(ToAdd);
}
What I want to do know, is include "What muscle groups does the exercise hit?", and then a multichoice with mentioned muscle groups. My idea is that it would look something like this:
1. Chest
2. Shoulders
3. Arms
4. Legs
5. Back
6. That is all
As long as the person kept choosing 1-5 the exercise would acquire the enum attributes, and then quit the loop once the person chose 6, but I have no idea how to do this part. From most Ive seen about enums they are mostly used in the string format and parsing, so I have no idea how to assign attributes by reading integer. And the hardest part is assigning several of them.
Here is my enum, by the way:
[Flags]
public enum BodyParts : int
{
None = 0,
Chest = 1,
Shoulders = 2,
Biceps = 4,
Triceps = 8,
Back = 16,
Legs = 32
}
Thank you for your answers.
You can have a lookup table connecting string answer to enum values
var lookup = new Dictionary<string,BodyParts > () {
{ "chest" , BodyParts .Chest},
{ "shoulders " , BodyParts .Shoulders}
...
};
and use it like this
string name = Console.ReadLine().ToLower;
var bodypart = BodyParts.None;
lookup.TryGetValue(name, out bodypart);
katalog.Add(bodypart));
Use a CheckedListBox where the items are the instances of the enum.
var clb = new CheckedListBox();
foreach (BodyParts bp in Enum.GetValues(typeof(BodyParts)))
clb .Items.Add(bp);
Then to get the flagged combination of all checked items, just bitwise or (combine them). The result will be a bitmask that has all the selected body parts.
var result = clb.CheckedItems
.Cast<BodyParts>()
.Aggregate(BodyParts.None,
(current, bp) => current | bp);
I think my query is not working because of the enum flag I have.
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4,
Full = 8
}
dbContext.UserStorages.FirstOrDefault(x => x.Permission.HasFlag(Permissions.Write));
In my sql database the column is an "int" column. and right now has a value of "8" if I change it to Permissions.Full then I will get the record back.
Permissions.Full shouldn't be 8 but 7 if it means Read + Write + Delete. In binary
Read -> %001
Write -> %010
Delete -> %100
Full -> Read | Write | Delete -> %001 | %010 | %100 -> %111 -> 7
In your case you are asking whether the second bit (i.e. %0010) is set in %1000 which obviously it isn't.
This is mostly academic in nature. Just attempting to understand why this doesnt work and how to do it properly.
I store in my database a 0 1 or 2 where each represent a different status flag. (this cant be changed its in production)
In my code I have an enum
public enum Status{
Active = 0,
Voided = 1<<0,
Refunded = 1<<1
}
What I want to do is turn the database value into my enum with as little code as possible.
I am sure I could do some crazy walk through like this
If(dbValue == 0)
return Status.Active;
else if(dbValue == 1)
return Stats.Voided;
... and so on
But I was curious if there was a simpler way.
Basically how do I quickly convert between an Int32 and a bit shifted enum with as little code as possible.
I tried doing this
return dbVal | Status.Active;
return 1 << Convert.Int32(dbValue);
and a couple other variations but nothign seems to work/
For the enum you show, the following will work:
int dbValue = ...;
var status = (Status)dbValue;
If the database value can only take one of three values - 0 (Active), 1 (Voided), 2 (Refunded) - then it would probably be clearer to make your enum the following equivalent.
public enum Status
{
Active = 0,
Voided = 1,
Refunded = 2
}
The bit shifts you use suggest a bit field, but that's not what you actually are dealing with. It wouldn't make sense to have Status.Voided | Status.Refunded;.
I'm plan to make a page that displays info about user's in the form of a table. Each column will be a property of the table. I want someone viewing the table to be able to choose ways to filter the users. There will be two check boxes: 1 for reported users and 1 for creation date. I'm planning to make an enum called UserFilter like so:
public enum UserFilter
{
None = 0,
Date = 1,
Reported = 2
}
If I need to add another type it's value will be set to 4 so that I can tell which enums are selected through a bitwise or (3 would be both 1 and 2). The problem I'm having is with reading in an enum from the query string. I guess I could do something like posting back with an int (0 for none, 1 for date, 2 for report, 3 for both) but I would like to try posting back with the actual string. I'm not sure how I would parse "Date|Reported" into an enum value that doesn't exist in UserFilter.
In a nutshell: Is there a clean way to parse "Date|Reported" into the value 3 without adding another value to my enum?
You could try something like
string enumString = "Date|Reported";
UserFilter uf = enumString.Split('|').ToList().Select(e =>
{
UserFilter u;
Enum.TryParse(e, true, out u);
return u;
}).Aggregate((u, c) => u = u | c);
I would however recomend that you change your enum to
public enum UserFilter
{
None = 1,
Date = 2,
Reported = 4
}
as if you have it your way None|Date is the same as Date, because 0 + 1 => 1
EDIT
As #ScottSelby stated, this would also work
UserFilter u = (UserFilter) 3;
//or 6 rather than 3 if you take my comment above into consideration
The system have a plain enum like this,
public enum SomeEnum : short
{
Ok = 0,
Missing = 17,
};
This enum are now into a situation where I need to mask some more information into it without change the appearence of the existing enum values. The enum will got some new values,
[Flags]
public enum SomeEnum : short
{
Ok = 0,
Missing = 17,
Blocking = 18, // Values could be anything
Low = 19, // Values could be anything
};
I was afraid there could be problem to the current enum usage. It appears that I'm right, but I hope i'm proved wrong with your help. The usage until today are built around SomeEnum.Ok. Also tomorrow, but the Ok need additional info. I need to mask the enum values without affect it's current behavior, which could came from any common reference;
someEnumVariable.ToString()
(int)someEnumVariable
someVar = SomeEnum.Ok
Enum.Parse(typeOf(SomeEnum), someString)
If I flag the enum with
var test = (SomeEnum.Ok | SomeEnum.Blocking);
Both flags can be founded i.e. test.HasFlags(SomeEnum.Ok) or test.HasFlags(SomeEnum.Blocking) but the enum represents as SomeEnum.Blocking, which aren't possible.
Any ideas?
Because the value of SomeEnum.OK is 0, calling HasFlag(SomeEnum.OK) will always return true. When you mask enums together, the process relies on the fact that the sum of any combination of enum values will be unique. Typically you would set these up starting using values of 2^0, 2^1, 2^2, etc. For example:
[Flags]
public enum SomeEnum : short
{
Ok = 1,
Missing = 2,
Blocking = 4, // Values could be anything
Low = 8, // Values could be anything
}
If you want to mask the values together, you'll have to use the Flags attribute. If you can't refactor and change the value of SomeEnum.OK, then you may have to rely on passing in a SomeEnum[], rather than a single masked SomeEnum value.
EDIT
Just a quick note on masking the values together using the enum defined above. Take the following code:
var t1 = (int)(SomeEnum.OK | SomeEnum.Missing); //t1 = 1 + 2 = 3
var t2 = (int)(SomeEnum.Missing | SomeEnum.Blocking); //t2 = 2 + 4 = 6
var t3 = (int)(SomeEnum.OK | SomeEnum.Low); //t3 = 1 + 8 = 9
var t4 = (int)SomeEnum.OK; //t4 = 1
var s1 = (SomeEnum.Ok).ToString(); //s1 = "Ok"
var s2 = (SomeEnum.Ok | SomeEnum.Missing).ToString(); //s2 = "Ok, Missing"
When these items are OR'ed together, .NET just adds the values together to produce a new, unique value that represents the combination of the OR'ed items. Using enum values that are powers of 2 ensures that the combinations will always be unique.
http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx
I think a quick introduction to binary OR is in order.
| doesn't just let you sneak two integers into one variable. It performs a mathematical operation.
Therefore, any value other than 0 OR'ed with 0 will return that value itself.
You will probably encounter further unexpected behavior if you supply flag values that are not a single bit, such as 1, 2, 4, 8, 16.
EDIT
If you want to build a Flags enum around the existing values, you can do that. Don't use the currently reserved bits 10001 (17) for any other value, and be careful when testing for Ok.
Here's an example of how to accomplish this using a bitflag. This will however likely force you to change your existing flag comparisons.
[FlagsAttribute]
enum tester
{
alpha = 1,
beta = 2,
gamma = 4,
reggy=3
}
class Program
{
static void Main(string[] args)
{
tester t = tester.alpha | tester.beta;
if (t == tester.alpha)
Console.WriteLine("alpha only");
if ((t & tester.alpha) != 0)
Console.WriteLine("alpha");
if ((t & tester.beta) != 0)
Console.WriteLine("beta");
if ((t & tester.gamma) != 0)
Console.WriteLine("gamma");
if (t == (tester.beta | tester.alpha))
Console.WriteLine("alphabeta");
//this will produce alpha, beta, alphabeta