35

I've got an enum defined like this

enum Tile { Empty, White, Black };

But let's suppose when written to the console,

Console.Write(Tile.White);

I want it to print

W

Or any other value, I could use a switch for this, but is there a nicer way? Perhaps using attributes?


Here's what I have in mind. Writing something like this,

[AttributeUsage(AttributeTargets.Field)]
public class ReprAttribute : Attribute
{
    public string Representation;
    public ReprAttribute(string representation)
    {
        this.Representation = representation;
    }
    public override string ToString()
    {
        return this.Representation;
    }
}

enum Tile { 
    [Repr(".")]
    Empty, 
    [Repr("W")]
    White, 
    [Repr("B")]
    Black 
};

// ...
Console.Write(Tile.Empty)

Would print

.

Of course, that override string ToString() didn't do what I was hoping it would do (it still outputs "Empty" instead.


This article summarizes it pretty well: http://blogs.msdn.com/b/abhinaba/archive/2005/10/20/c-enum-and-overriding-tostring-on-it.aspx

2
  • Sounds like you are trying to stuff too much into a simple enum...and trying to override the behaviour of a well defined method. You'd be much better off using an array/collection of objects. Commented Sep 2, 2010 at 8:59
  • possible duplicate of C# String enums Commented Jun 8, 2013 at 22:58

8 Answers 8

51

You could use attributes :

using System.ComponentModel;

public enum Tile
{
    [Description("E")]
    Empty,

    [Description("W")]
    White,

    [Description("B")]
    Black
}

And an helper method :

public static class ReflectionHelpers
{
    public static string GetCustomDescription(object objEnum)
    {
        var fi = objEnum.GetType().GetField(objEnum.ToString());
        var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
        return (attributes.Length > 0) ? attributes[0].Description : objEnum.ToString();
    }

    public static string Description(this Enum value)
    {
        return GetCustomDescription(value);
    }
}

Usage :

Console.Write(Tile.Description());
Sign up to request clarification or add additional context in comments.

2 Comments

That's close to what I had in mind... but I was hoping I could drop the .Description() bit, and it would just call whatever converter/to string method when I try to print the tile directly. Basically, overriding the ToString() method with a value it gets from the attribute instead.
I'll give you the check for being closest to what I was after; it seems you can't do it without explicitly calling a conversion method.
25

You can use the ToString() method:

Tile t = Tile.White;
Console.WriteLine(t.ToString()); // prints "White"
Console.WriteLine(t.ToString().SubString(0, 1)); // prints "W"

Comments

18

The naive non-attribute way:

public enum Tile {
    White = 'W',
    Black = 'B'
} 
//...
System.Diagnostics.Debug.WriteLine(string.Format("{0} - {1}", Tile.White.ToString(), (char)Tile.White));
//Prints out:
//White - W

Comments

14
Enum.GetName(typeof(Tile), enumvalue)

This will get the enum as string.

Comments

3

I suggest a combination of the enum and a static Dictionary (and an extension method).

It will avoid the (expensive) reflection and has a clean structure. You can optimize the naming further to make it even more convenient.

public enum OrderStatus
{
    Ready,
    InProduction,
    Completed
}

public static class EnumRelations
{
    public static Dictionary<OrderStatus, string> OrderStatusToString = new Dictionary<OrderStatus, string>()
    {
        { OrderStatus.Ready, "Ready" },
        { OrderStatus.InProduction, "In Production" },
        { OrderStatus.Completed, "Completed" },
    };
}

public static string GetEnumString(this OrderStatus os)
{
    var str = OrderStatusToString[os];
    return str;
}

var str = OrderStatus.Ready.GetEnumString();

Comments

2

You could use a combination of Enum.GetName and Substring.

Something along the lines of:

private string GetShortName(Tile t)
{
    return Enum.GetName(typeof(Tile), t).Substring(0, 1);
}

...

Console.WriteLine(GetShortName(Tile.White));

Comments

0

You could try the following:

private string GetFirstEnumLetter(Tile tile)
{
    if (tile.ToString().Length > 0)
    {
        return tile.ToString().Substring(0, 1);
    }

    return string.Empty;
}

And then convert it every time you want by calling:

Console.Write(GetFirstEnumLetter(Tile.White));

Hope that helps.

Comments

0

In Java, you'd do this (wrote this before noticing this is a C# question, sorry! But it might be useful to someone...):

public enum Tile {

    Empty ( "." ), White ( "W" ), Black ( "B" ) ;

    private String abbr;

        //Note this is private
    private Tile ( String abbr ) {

        this.abbr = abbr;
    }

    public String getAbbr () {

        return abbr;
    }

        //The following is only necessary if you need to get an enum type for an abbreviation
    private static final Map<String, Tile> lookup = new HashMap<String, Tile>();

    static {
        for ( Tile t : EnumSet.allOf( Tile.class ) )
            lookup.put( t.getAbbr(), t );
    }

    public static Tile get ( String abbr ) {

        return lookup.get( abbr );
    }
}

public class TestTile {

public static void main ( String[] args ) {

    System.out.println(Tile.Black.getAbbr());
    System.out.println(Tile.White.getAbbr());
    System.out.println(Tile.Empty.getAbbr());

    System.out.println(Tile.get( "W" ));

}

}

Output:

B

W

.

White

This gives you 2-way translation into and from an enum.

You can't just print Tile.White and expect it to print something else, so you do need to call Tile.White.getAbbr(). Just printing Tile.White will call toString() on the enum, which will print the name. I guess you could override toString() if you really wanted:

public String toString(){
    return getAbbr();
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.