I have an enum like so.
public enum TimeFrame
{
Morning = 1,
Afternoon,
Evening
}
When an object containing a property of type TimeFrame is stored, there's a conversion using a switch statement making each value explicitly to 1, 2, and 3. The command string created is substituted from e.g. Evening to 3. The same when fetching from the DB - if there's a value of 1, it's being mapped manually and explicitly into Morning.
Is there a smooth way to storage the values of the enum "as is"? Or should we avoid doing so for a reason?
I've tried straight-off approach but that only gives the fall-back value all the way...
TimeFrame = row["TimeFrame"] as TimeFrame? ?? TimeFrame.Morning
You can cast enums to ints and vice versa, this is very fast. You can also convert between enums and strings, takes a bit more code, time, and storage. You can then trivially store ints or strings in your database.
If for some reason the O/R-mapper (or whatever technology you are using) cannot handle enum values, you can create an int property translating your enum:
// Do not map!
public TimeFrame TimeFrame { get; set; }
// Map!
public int TimeFrameInt {
get { return (int)TimeFrame; }
set { TimeFrame = (TimeFrame)value; }
}
The translation between ints and enums is simply done with casts; no switch statements required. This is possible and very fast, since enums are represented by ints under the hood.
Related
I have a struct for a game I am building that looks like this:
using System;
public readonly struct Target
{
public Target((int Min, int Max) range, string[] targetTypes)
{
Range = range;
TargetType = ParseTypes(targetTypes);
}
public (int Min, int Max) Range { get; }
public TargetTypes TargetType { get; }
[Flags]
public enum TargetTypes { None = 0, Self = 1, Enemy = 2, Player = 4, Character = 8, Area = 16 }
}
I would like to take all of the values in the string array and cast them into a single enum (not an array of enum values, which I believe is what is happening in the answer to this question).
The thing is a Target can have multiple types. I figured an enum was the best way to represent this, and also figured defining the enum inside the struct wasn't a terrible idea, but this could be an anti-pattern (coming from a JS background, be gentle!).
I like this whole enumeration types as bit flags thing, hence the numbering, that's what sent me down this path.
Yes, I control the inputs, so happy to hear why/how I should do this differently - thanks for your time!
You could use the following.
TargetType = (TargetTypes)Enum.Parse(typeof(TargetTypes),string.Join(",",targetTypes));
The second parameter of Enum.Parse accepts either a single value/constant representing the enum or a list of named constants or underlying values delimited by commas (,).
Thank you #asawyer for pointing the way. I missed an important part of the documentation (always RFTM twice!):
Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
There's no need for anything fancy here, Parse does the trick:
TargetType = (TargetTypes) Enum.Parse(typeof(TargetTypes), string.Join(",", targetTypes));
I'm working with pulling a stream of bytes off of a medical device, and have run into a really annoying data structure. Basically, I am getting back a 2-byte chunk where each bit represents a boolean value. This structure appears frequently enough in the byte stream to develop a struct/class around it, but in each instance, the bits mean completely different things.
So first I set up a bunch of Enums to represent all the different definitions the bit structure could have. (Note that not every bit is used in every definition. Sometimes there are breaks in between the important bits.)
EDIT: Removed all names that looked like 'flag.' I'm not using the [Flags] attribute, and this seems to be a point of contention/confusion. The enum values are simply mapped to the indices in my BitArray.
public enum RecordInfo { AM_TEST = 0, PM_TEST, TEST_VALIDITY };
public enum RecordAlerts { ALERT1 = 0, ALERT2, ALERT3, ALERT4, VALIDATED = 15 };
Then created this container to hold the actual bits:
public struct TwoBytes<TEnum> where TEnum : struct, IConvertible
{
private BitArray _bits = new BitArray(2);
}
This seems to work as I need, until I want to index my structure based on an Enum name. So say I have a TwoByte struct called Alerts, and this contains some bit values. If I want to get a specific flag like this:
bool alert3Set = Alerts[RecordAlerts.ALERT3]
I end up with a truly heinous index function. This is what I have in place now:
public bool this[TEnum name]
{
get
{
int index = Enum.GetValues(typeof(TEnum)).Cast<TEnum>().ToList().Where(x => x.Equals(name)).Cast<int>().First();
return _bits[index];
}
}
Now it works, crazily enough. But that LINQ chains looks positively atrocious, and it takes a while to decipher what it's actually doing.
Is there a cleaner, more efficient way of converting a generic Enum 'name' to its integer value? Or would I be better suited to use a Dictionary (or some other object) to represent the bit structure definitions?
As long as every TEnum you'd use derives from int (the default), and not from another number type, this will work:
public bool this[TEnum name]
{
get
{
int index = (int)(object)name;
return _bits[index];
}
}
If you want to support enums derived from smaller types (and enums that only use values within the range supported by int), I'd use:
public bool this[TEnum name]
{
get
{
int index = Convert.ToInt32(name);
return _bits[index];
}
}
(fully supporting enums derived from types that can't implicitly be converted to int, like uint, long, and ulong, gets more complicated, because BitArray's indexer uses an int)
I think a bit of OOP would make your life easier. You can introduces classes that represent the data you receive, and has meaningful property names. Each class could accept your BitArray into constructor and parse it into properties.
Further in your program you could use these classes instead of fiddling with bits.
As FrankPI suggested in the comments, why not use an enum whose values really represent each bit, rather than using an intermediate BitArray?
[Flags]
public enum RecordFlags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8, FLAG5 = 0x10, VALIDATED = 0x8000 };
var readFlags = (RecordFlags) ((bytes[0] << 8) | bytes[1]);
bool hasFlag2 = (readFlags & RecordFlags.Flag2) != 0;
I've declared an enum type,
assigned a variable to it
and now I am writing it to the console.
So what use does an enum type have in a real world application?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Enum
{
enum cars
{
Toyota, Nissan, Ferrari, Lamborghini
}
}
class Program
{
enum cars
{
Toyota, Nissan, Ferrari, Lamborghini
}
static void Main(string[] args)
{
int a = (int)cars.Ferrari;
Console.WriteLine(a);
}
}
}
Whenever a procedure accepts a limited set of variables, consider using an enumeration. Enumerations make for clearer and more readable code, particularly when meaningful names are used.
The benefits of using enumerations include:
Reduces errors caused by transposing or mistyping numbers.
Makes it easy to change values in the future.
Makes code easier to read, which means it is less likely that errors
will creep into it.
Ensures forward compatibility. With enumerations, your code is less
likely to fail if in the future someone changes the values
corresponding to the member names.
ref : MSDN
enum cars
{
Toyota, Nissan, Ferrari, Lamborghini
}
This isn't the best example, as there are way more types of car than that, and new car manufacturers pop up regularly, e.g. tiny custom shops.
What would I use an Enum for?
You'd use it for something that has more than once choice, but those choices are discrete, and aren't going to change (very often).
You'd use it in places that might otherwise require a string, but where you don't want to accept just any string.
Something like:
public enum DayOfWeek
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
public void ScheduleRecurringAppointment(DayOfWeek day)
{
// Todo: Add appointment to DB here...
}
(note that this isn't an enum you should write yourself. There is one in the .Net framework already).
You can change enums, but it is painful, as you have to recompile all code that uses the enum.
You want to use enum values in your program to improve code clarity and make it easier to maintain. Enums provide better error-checking and compiler warnings. They store constants and important values. Check the Enums for a better clarification.
EDIT:
Enums can be used with IntelliSense in Visual Studio in real world
application.
They come in handy when you wish to be able to choose between a set
of constant values, and with each possible value relating to a
number, they can be used in a wide range of situations.
An enumeration type provides
an efficient way to define a set of named integral constants that may
be assigned to a variable.
One thing no-one has pointed out yet (unless I missed it) is the use of Enumeration Types to set bit flags. You can do bitwise operations (such as & and |) on enum values and also bitwise comparisons. This works with the FlagsAttribute attribute.
[Flags]
enum Days
{
None = 0x0,
Sunday = 0x1,
Monday = 0x2,
Tuesday = 0x4,
Wednesday = 0x8,
Thursday = 0x10,
Friday = 0x20,
Saturday = 0x40
}
class MyClass
{
Days meetingDays = Days.Tuesday | Days.Thursday;
}
This would probably be more useful:
public enum Transmission {
Manual,
Automatic,
SemiAutomatic
}
public class Car
{
public Transmission CarTransmission { get; set; }
}
Enum class contains many useful methods for working with enumerations. The beauty of enum is that your can process it as integer value and display as string.
You can find more in >> http://www.c-sharpcorner.com/uploadfile/puranindia/enums-in-C-Sharp/
You can variables of your enum type. They will only accept the values of the enum and that makes coding easier (I think)
For example:
Enum Cars { VW, Mercedes, Ford, Opel };
...
Cars myCar = Cars.VW;
Enums are for code readability, and can be used to restrict a type to a finite set of values.
A common use of Enums is for modelling of States in a business process - i.e. New States cannot be added on an adhoc basis, and would require further coding and testing.
The following are advantages of using an enum :
You clearly specify for client code which values are valid for the
variable.
In Visual Studio, IntelliSense lists the defined values.
Heres an example of using enums in asp.net to change the header texts of each column. I Used the enum to specify the index of which column in the gridview I want to alter.
private enum MENU_ITEM
{
Customer_ID = 0,
Customer_First_Name = 1,
Customer_Surname = 2,
Customer_DOB = 3,
Customer_Phone_Number = 4,
Customer_Email = 5,
Customer_Update = 6,
Customer_Delete = 7,
Customer_Transaction = 8
}
private void populateGridHeader()
{
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_ID].Visible = false;
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_First_Name].HeaderText = "First Name";
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_Surname].HeaderText = "Surname";
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_DOB].HeaderText = "Date of Birth";
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_Phone_Number].HeaderText = "Phone Number";
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_Email].HeaderText = "Email";
SearchCustomer_g.Columns[(int)MENU_ITEM.Customer_Transaction].HeaderText = "New Transaction";
}
I have a field that indicates whether someone wars a commission or a fee.
In sql its going to be a bit field.
How should I name it?
You might want to use an enum instead of a bool.
public enum Payment
{
Commission = 0,
Fee = 1
}
You can then cast it to an integer when necessary.
class Thing
{
Payment ThingPayment { get; set; }
}
var thing = new Thing();
thing.ThingPayment = Payment.Fee;
int bitValue = (int)thing.ThingPayment;
The simplest thing would be to call it IsCommission (or IsFee). In C# boolean properties should generally start with 'Is' or 'Has' unless the name already implies the boolean nature. If there is a possibility of other values being added to the equation later, seriously consider making it an enumeration now. In that case, you might call it CompensationMethod, but there are quite a lot of good possible names there. If you decide to stick with boolean, which might be a good idea if your database field will remain boolean, you could expose the converse of your property like this:
protected bool isCommission
public bool IsCommission
{
get { return isCommission; }
set { isCommission = value; }
}
public bool IsFee
{
get { return !isCommission; }
set { isCommission = !value; }
}
My 2 rappen, I would have "IsFee" with an extended property to explain it more.
However, at the risk of YAGNI, would have have other types? Such as "retrocession" or "holding fee" as opposed to "payment fee". In which case, a tinyint lookup to another table in SQL.
And as mentioned, a c# enumeration to make things easier.
I would hesitate to use a bit for this. You have a one-to-many relationship going which by coincidence has two possible values. But there could be more relationship values in the future. Somebody might work for free, or require a fee and a commission, or a flat fee if the amount in question is less than a certain fixed amount.
Instead, use a relational table to hold the values. You will give your design more flexibility in the end. You also obviate the need to store any constants in your code.
EDITED: Updated 3/23/09. See rest of post at bottom. I'm still having trouble with the indexer. Anymore help or examples would really help me out.
Write a class, MyCourses, that contains an enumeration of all the
courses that you are currently taking.
This enum should be nested inside of
your class MyCourses. Your class
should also have an array field that
provides a short description (as a
String) of each of your courses. Write
an indexer that takes one of your
enumerated courses as an index and
returns the String description of the
course.
Write a class MyFriends that contains an indexer that provides
access to the names of your friends.
namespace IT274_Unit4Project
{
public class MyCourses
{
// enumeration that contains an enumeration of all the courses that
// student is currently enrolled in
public enum CourseName {IT274= 0,CS210 = 1}
// array field that provides short description for each of classes,
// returns string description of the course
private String[] courseDescription =
{"Intermediate C#: Teaches intermediate elements of C# programming and software design",
"Career Development Strategies: Teaches principles for career progression, resume preparation, and overall self anaylsis"};
// indexer that takes one of the enumerated courses as an index
// and returns the String description of the course
public String this[CourseName index]
{
get
{
if (index == 1)
return courseDescription[0];
else
return courseDescription[1];
}
set
{
if (index == 1)
courseDescription[0] = value;
else
courseDescription[1] = value;
}
}
}
}//end public class MyCourses
I'm working on this homework project and having trouble understanding the text explaining how to correctly take the accessed value of the enumeration and then apply the string array value to it. Can you please help me understand this? The text we are using is very difficult and poorly written for a beginner to understand, so I'm kind of on my own here. I've got the first parts written, but need some help on the accessing of the enumeration value and assigning, i think i'm close, but don't understand how to properly get and set the values on this.
Please do not provide me with direct code answers, unless a MSDN style explanation that is generalized and not specific to my project. ie:
public class MyClass
{ string field1;
string field2;
//properties
public string Value1
get etc...
Thanks!
First of all, the base type of an enumeration has to be a numeric value type, so you can't have an enumeration with base type string. The following isn't going to compile:
public enum CourseName
{
Class1 = "IT274-01AU: Intermediate C#",
Class2 = "CS210-06AU: Career Development Strategies"
}
So change it to use the default base type of int. Something like the following will do, but change the names as you see fit (you might want to use the course name instead of the code, for example). Remember also that you should use meaningful names whenever possible in an enumeration.
public enum Courses
{
IT274_01AU,
CS210_06AU
}
(I know you said you didn't want specific code examples, but I think this one illustrates my point much more clearly than any explanation.)
Second, you're on the right track with the indexer, but you have to think of how to relate the enumeration to the array of string descriptions. Remember, an enumeration is nothing more than a finite set of glorified (named) numbers. With the above Courses enumeration, you have two values named IT274_01AU and CS210_06AU. So in the indexer, you have to map each of these values to the string description. There are multiple ways to do it, but the simplest one would be a switch statement, for example:
switch (myEnum)
{
case value1:
return string1;
case value2:
return string2;
}
Another option, however is to explicitly map the enum values to its base type, and use the base type to index into your array. For example, if you have the enum
public enum Enumerations
{
value1 = 0,
value2 = 1
}
then you can index directly into an array using myArray[(int)myEnum]. This may be of use and is the slightly-more-advanced-but-less-lines-of-code-and-arguably-easier-to-understand method.
(resisting the urge to write code)
First off, an enumeration is a named list of integers and (per MSDN) the approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
Also, remember that courseDescription is an array of strings and the purpose of the indexer is to give you an index into that array (ie. [0] returns the first string, [1] returns the second, etc.).