Say I have enum as follows (taken from MSDN example):
enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
I can then use is in the code as follows:
int today = (int)Days.Sun;
Question:
Can I evaluate enums? Say I have a variable Day whose value is "Sun".
Will Days.Day evaluate to Days.Sun?
Thanks!
Please don't get hung up on the days example and tell me I should use comparison etc...i am looking to replace the usage of arrays with enums as it is more compact. So what I am looking for is essentially an ability to retrieve values from enum similar to an array:
myArray[Day] where day will evaluate to array key....
Am I right in saying you've got:
string day = "Sun";
and you want to get back the value Days.Sun?
If so, use:
string day = "Sun";
Day day = (Day) Enum.Parse(typeof(Days), day);
Yes, you can do that. You can freely cast between an enum and its underlying type.
using System;
class Program
{
static void Main()
{
// prints "zero"
Console.WriteLine((Foo)0);
// prints "1"
Console.WriteLine((int)Foo.one);
}
}
enum Foo { zero, one, two };
You can also parse the string values as well. Using Enum.Parse
[TestFixture]
public class EnumParsingSO
{
public enum Days
{
Sat = 1,
Sun,
Mon,
Tues
}
[Test]
public void EnumFromString()
{
Days expected = Days.Mon;
int expectedInt = 3;
Days actual = (Days)Enum.Parse(typeof(Days), "Mon");
Assert.AreEqual(expected, actual);
Assert.AreEqual(expectedInt, (int)actual);
}
}
As Andrew says, you can cast from an enum to its underlying type. You can also unbox between the two as well, and there's an implicit conversion from the constant 0 to any enum type:
using System;
enum Demo { Foo, Bar, Baz };
class Test
{
static void Main()
{
int i = 2;
object o = i;
// Unboxing from int to Demo
Demo d = (Demo) o;
Console.WriteLine(d);
o = Demo.Baz;
// Unboxing from Demo to int
i = (int) o;
Console.WriteLine(i);
// Implicit conversion of 0
d = 0;
Console.WriteLine(d);
}
}
for int yes , but for string you should do something like this
Yes you can, you just need to provide the native integer value for each enum value. From your example:
enum Days {
Sat=1,
Sun=2,
Mon=3,
Tue=4,
Wed=5,
Thu=6,
Fri=7
};
(Now, why you would order days of the week in this way is beyond me...)
Related
While I code every time I used List<T>, string, bool etc. I did't see anywhere a use of an enum. I have an idea that enum is a constant but in practice, where do we actually use it. If at all we can just use a
public const int x=10;
Where do we actually use it?
Kindly help me
An enum is a convenient way to use names instead of numbers, in order to denote something. It makes your code far more readable and maintainable than using numbers. For instance, let that we say that 1 is red and 2 is green. What is more readable the following:
if(color == 1)
{
Console.WriteLine("Red");
}
if(color == 2)
{
Console.WriteLine("Green");
}
or this:
enum Color { Red, Green}
if(color == Color.Red)
{
Console.WriteLine("Red");
}
if(color == Color.Green)
{
Console.WriteLine("Green");
}
Furthermore, let that you make the above checks in twenty places in your code base and that you have to change the value of Red from 1 to 3 and of Green from 2 to 5 for some reason. If you had followed the first approach, then you would have to change 1 to 3 and 2 to 5 in twenty places ! While if you had followed the second approach the following would have been sufficient:
enum Color { Red = 3 , Green = 5 }
A constant lets us define a name for a value in one place in our code.
An enum is like defining a set of constants and lets us declare variables, properties, and parameters that can only use one of those constants.
For example, suppose we have a SalesOrder class for orders we receive on a website, and each SalesOrder can have a status - perhaps New, Shipped, Canceled, etc.
We could do it like this:
public class SalesOrder
{
public string OrderStatus {get;set;}
But then someone could set that property to something completely invalid, like
order.OrderStatus = "Hello!";
We could decide that we'll give each status a number instead to prevent someone using some crazy value. So we change it to
public class SalesOrder
{
public int OrderStatusCode {get;set;}
and we decide that 1 = New, 2 = Shipped, 3 = Canceled, etc. But that still doesn't fix anything, because someone can set OrderStatusCode = -666 and we're still messed up.
In any one of these cases we could improve on this with constants, like
const string SHIPPED_ORDER_STATUS = "Shipped";
or
const int NEW_ORDER_STATUS_CODE = 1;
But that still doesn't really solve the problem. It helps us to do this:
order.OrderStatusCode = NEW_ORDER_STATUS_CODE;
and that's good. But it still doesn't prevent this:
order.OrderStatusCode = 555; //No such order status code!
An enum lets us do this:
public enum OrderStatuses
{
New,
Shipped,
Canceled
}
public class SalesOrder
{
public OrderStatuses OrderStatus {get;set;}
Now it's impossible to set OrderStatus to any invalid value. It can only be one of the values in OrderStatuses.
Comparisons become a lot easier too. Instead of
if(string.Equals(order.OrderStatus,"shipped",Ordinal.IgnoreCase))
or
if(order.OrderStatusCode == 3) //What does three mean? Magic number!
We can do
if(order.OrderStatus == OrderStatuses.Shipped)
Now it's readable and easier to maintain. The compiler will prevent using any invalid value. If you decide you want to change the name of a value in OrderStatuses you can just right-click and rename it. You can't do that with a string or an int.
So an enum is very useful in that scenario - if we want to have a type with a limited, predefined set of values.
The most common use for constants is if we're putting a string or a number in our code that either repeats or has no apparent meaning, like
if(myString.Length > 434) //What is 434? Why do I care if it's more than 434?
We might declare a constant like
const int MAX_FIELD_LENGTH = 434;
Now this makes sense:
if(myString.Length > MAX_FIELD_LENGTH) //Now it's obvious what this check is for.
It's a small detail but it signals our intent and keeps us from storing a value in multiple places.
Suppose you need to flag users in a software with roles, then you can declare an enum to define these roles, for sample:
public enum UserRole
{
Master = 1,
Developer = 2,
Tester = 3,
Manager = 4
}
Then, you can use this type UserRole in your User entity. It work as an integer value but it is more legible than an integer.
You could implement something like this:
if (user.Role == UserRole.Master) {
// some action for master
} else if (user.Role == UserRole.Developer) {
// another action for developer
}
or
switch (user.Role)
{
case UserRole.Master:
// some action for master
break;
case UserRole.Developer:
// some action for developer
break;
case UserRole.Tester:
// some action for tester
break;
case UserRole.Manager:
// some action for manager
break;
}
Just adding a little bit more on enums: Enumerators are named constants. If you are using a set of named constants in your application you can go with enums instead of hard coding those constants. Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of enumeration elements is int. But you can change the default type.
enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};
By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1. For example, in the following enumeration, Sat is 0, Sun is 1, Mon is 2, and so forth. You can change the first value
enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
The sequence of elements is forced to start from 1 instead of 0.
You can change the default type of enum, But must be any integer type.
enum Days : byte {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
Practical Scenario
You can create a enum of status of your project Task
public enum Status
{
started,
completed,
notstarted
}
And you can use the enum like
Status.started
This relates to my Are there any project templates for using T4 to generate classes? question. I have lists of string (nvarchar) parameter values I need to generate properly typed class properties for.
The values are all primitives - the most complex being DateTime - in the set { int, double, bool, DateTime }. Currently I have hand coded typed properties for one - of many - such lists, and to parse the string I start with DateTime.TryParseExact. If that fails, I try Double.TryParse, and at the bottom I give up guessing and assume it really is a string.
Is this a fairly sound approach, or are there other more complicated or accurate methods I should rather use?
If the set of values was only [double, DateTime, bool] this would be an exhaustive but fairly sound method. There is simply so overlap between those sets (true is always a bool and 5 is never a bool).
Having both int and double makes this proposition a bit flaky because there is a large amount of overlap. Essentially any int can be also seen as a double. How am I to interpret for example 4 if it appears in the value set? It could be interpreted both ways and if values change over time you could see the type of your generated code changing as well.
Consider if a column always had whole numbers simply by coincidence. Hence you generated int value and wrote a bit of code that depended on them being int. Then a month or so later a non-whole number was added and suddenly you are spitting out double values. This would probably have a non-trivial affect on your code.
Personally the approach I would take is to simply have another table which dictated the type of the contents.
Have a look at Convert.ChangeType and TypeDescriptor.GetConverter.
I've written an extension method to do this for me:
public static T Convert<T>(this object obj)
{
T result;
try
{
result = (T)System.Convert.ChangeType(obj, typeof(T));
if (object.ReferenceEquals(result, null))
{
var typeConverter = !obj.IsNullable()
? TypeDescriptor.GetConverter(typeof(T))
: new NullableConverter(typeof(T));
result = obj is string
? (T)typeConverter.ConvertFromString(obj as string)
: (T)typeConverter.ConvertTo(obj, typeof(T));
}
}
catch (Exception)
{
result = default(T);
}
return result;
}
public static bool IsNullable<T>(this T obj)
{
return Nullable.GetUnderlyingType(typeof(T)) != null;
}
Usage:
var itemsToConvert = new[] { "4", "5.98", "false", DateTime.Now.ToString() };
var #int = itemsToConvert[0].Convert<int>();
var #double = itemsToConvert[1].Convert<double>();
var #bool = itemsToConvert[2].Convert<bool>();
var #dateTime = itemsToConvert[3].Convert<DateTime>();
Console.WriteLine(#"int: {0}, Type: {1}", #int, #int.GetType());
Console.WriteLine(#"double: {0}, Type: {1}", #double, #double.GetType());
Console.WriteLine(#"bool: {0}, Type: {1}", #bool, #bool.GetType());
Console.WriteLine(#"DateTime: {0}, Type: {1}", #dateTime, #dateTime.GetType());
Output:
int: 4, Type: System.Int32
double: 5.98, Type: System.Double
bool: False, Type: System.Boolean
DateTime: 2013/08/21 06:01:07 PM, Type: System.DateTime
Hope this helps.
I have defined an enum and tried to retrieve it as follows
class Demo
{
enum hello
{
one=1,
two
}
public static void Main()
{
Console.WriteLine(hello.one);
Console.ReadLine();
}
}
Now, how do i retrieve the integer value "1" from the enum ?
There's an explicit conversion from any enum type to its underlying type (int in this case). So:
Console.WriteLine((int) hello.one);
Likewise there's an explicit conversion the other way:
Console.WriteLine((hello) 1); // Prints "one"
(As a side note, I'd strongly advise you to follow .NET naming conventions, even when writing tiny test apps.)
you can cast the enums like
int a = (int)hello.one
Well you can do a cast to int
Console.WriteLine((int)hello.one);
Try This.
Console.Writeline((int)hello.Value);
or
int value = Convert.ToInt32(hello.one);
OK, I don't think the title says it right... but here goes:
I have a class with about 40 Enums in it. i.e:
Class Hoohoo
{
public enum aaa : short
{
a = 0,
b = 3
}
public enum bbb : short
{
a = 0,
b = 3
}
public enum ccc : short
{
a = 0,
b = 3
}
}
Now say I have a Dictionary of strings and values, and each string is the name of above mentioned enums:
Dictionary<string,short>{"aaa":0,"bbb":3,"ccc":0}
I need to change "aaa" into HooBoo.aaa to look up 0. Can't seem to find a way to do this since the enum is static. Otherwise I'll have to write a method for each enum to tie the string to it. I can do that but thats mucho code to write.
Thanks,
Cooter
You'll have to use Reflection to get the underlying enum type:
Type t = typeof(Hoohoo);
Type enumType = t.GetNestedType("aaa");
string enumName = Enum.GetName(enumType, 0);
If you want to get the actual enum value, you can then use:
var enumValue = Enum.Parse(enumName, enumType);
Use
aaa myEnum =(aaa) Enum.Parse(typeof(aaa), "a");
You want to convert a string -> enum? This should help.
Just keep in mind that Enum.Parse isn't strongly typed... I reckon that will be a real limitation in your scenario. As you can see from Ngu's example you'd have to cast the output.
I am working on a basic Battleship game to help my C# skills. Right now I am having a little trouble with enum. I have:
enum game : int
{
a=1,
b=2,
c=3,
}
I would like the player to pass the input "C" and some code return the integer 3. How would I set it up for it to take a string var (string pick;) and convert it to the correct int using this enum? The book I am reading on this is bit confusing
Just parse the string and cast to int.
var number = (int)((game) Enum.Parse(typeof(game), pick));
// convert string to enum, invalid cast will throw an exception
game myenum =(game) Enum.Parse(typeof(game), mystring );
// convert an enum to an int
int val = (int) myenum;
// convert an enum to an int
int n = (int) game.a;
just typecasting?
int a = (int) game.a
If you're not sure that the incoming string would contain a valid enum value, you can use Enum.TryParse() to try to do the parsing. If it's not valid, this will just return false, instead of throwing an exception.
jp
The answer is fine but the syntax is messy.
Much neater is something like this:
public DataSet GetBasketAudit(enmAuditPeriod auditPeriod)
{
int auditParam =Convert.ToInt32(auditPeriod) ;