Can Enum values only be integer?

Asked

Viewed 1,209 times

7

Studying C#, I came across a situation, I want to receive a value (string) by the console. And then compare it to the value of a Enum. For example:

[Serializable]
public enum Command
{
    Exit            = "/exit",
    SendMessage     = "/msg",
    WhoIs           = "/whois"
}

And so, I want to compare the value and perform the proper actions:

switch(cmd)
    case Command.Exit:
    /* executa ações necessárias */

But it is giving problem, because the variable cmd is a string and I’m comparing a Enum. It is possible to use Enum for that? How to do? Have some better alternative?

2 answers

7


Enum represents a set (enumeration) of constants.
Each enumeration has an integer type associated with it, except char, the default type is int.
The types allowed are byte, sbyte, short, ushort, int, uint, long or ulong.

The type is assigned to the enumeration as follows:

public enum : long Command
{
}

The first enumeration value receives by default the 0, the value is then incremented by 1 and assigned to the following constant, the process is repeated for all constants.

Taking your example

public enum Command
{
    Exit,
    SendMessage,
    WhoIs
}

each constant receives the following values:

Exit = 0, SendMessage = 1 and WhoIs = 2

Default values can be replaced using initializers:

public enum Command
{
    Exit = 1,
    SendMessage,
    WhoIs = 4
}

The initializers, in addition to assigning a value to the constant, initialize the sequence of values of the following constants:

Exit = 1, SendMessage = 2 and WhoIs = 4

Having said that and answering your question the values of constants of a Enum may only be of the whole type.

However, resorting to the use of Attributes, we can do what you want.

First we write a class to represent this attribute, this class inherits from Attribute:

public class StringValueAttribute : Attribute
{
    //Propriedade que recebe a string que irá ser atribuída à constante
    public string StringValue { get; protected set; }

    //No construtor inicializa-se a propriedade
    public StringValueAttribute(string value)
    {
        StringValue = value;
    }
}  

To obtain the value of the attribute we use the Reflection.
To make things easier we will create the code as an extension method.

public static class ExtensionMethods
{
    public static string GetStringValue(this Enum value)
    {
        var type = value.GetType();

        FieldInfo fieldInfo = type.GetField(value.ToString());

        var attributes = fieldInfo.GetCustomAttributes(
            typeof(StringValueAttribute), false) as StringValueAttribute[];

        var stringvalue = attributes != null && attributes.Length > 0 ? attributes[0].StringValue : value.ToString();
        return stringvalue;
    }
}

Way to use

Attributes are first associated with the elements of the Enum

public enum Command
{
    [StringValue("/exit")]
    Exit,
    [StringValue("/msg")]
    SendMessage,
    [StringValue("/whois")]
    WhoIs
}

then to get the string, use the method GetStringValue().
You can’t use switch so use else if:

if(cmd == Command.Exit.GetStringValue())
{ 
    ......
    ......         
}
else if(cmd == Command.SendMessage.GetStringValue())
{
    ......
    ......         
}
else if(cmd == Command.WhoIs.GetStringValue())
{
    ......
    ......         
}    
....
.....

Note: If no attribute has been associated, the name of the constant is returned

Credits: The class Getstringvalue was written/adapted using existing information in net. Unfortunately I can’t remember where.

  • Opa ramaral, I tried to apply this method, but VS2013 points out an error that a constant value is expected. :/

  • Where? On which line?

  • About the value of the case: case Command.Exit.GetStringValue():

  • You’re right it can’t be used in switch. Utilize if()..else if()

  • 1

    I liked this implementation @ramaral. Helped me too.

4

In accordance with the documentation the only types accepted by Enum sane:

byte, sbyte, short, ushort, int, uint, long and ulong

I don’t use much C#, but in other programming languages, if I’m not mistaken, the use of Enum would be similar to several numerical constants with a namespace (is only an explanation for understanding, not quite that) with numerical values but represented by "texts", as the Exit that you created.

The idea is to receive "numbers" that will be compared with the structure of the ENUM. There may be more uses for this, but the basic use is always to use the structure of the ENUM to guide, without forgetting the meaning of that number, for example:

enviaSinal(Command.Exit);

This imaginary method will have the switch which will compare the sent command.

Now if what you want is to use "arguments" passed on a command line in your software, you can use an array, it would be something like:

IDictionary<string, string> Commands = new Dictionary<string, string>();
dict["Exit"]        = "/exit";
dict["SendMessage"] = "/msg";
dict["WhoIs"]       = "/whois";

You can also create a class with static variables (I don’t really know if this is the best way):

class Commands
{
    static readonly string Exit        = "/exit";
    static readonly string SendMessage = "/msg";
    static readonly string WhoIs       = "/whois";
}

Note that variables are read-only.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.