Boris Callens
Boris Callens

Reputation: 93357

Associating enums with strings in C#

I know the following is not possible because the Enumeration's type has to be an int

enum GroupTypes
{
    TheGroup = "OEM",
    TheOtherGroup = "CMB"
}

From my database I get a field with incomprehensive codes (the OEM and CMBs). I would want to make this field into an enum or something else understandable. Because if the target is readability, the solution should be terse.

What other options do I have?

Upvotes: 643

Views: 810258

Answers (30)

serge
serge

Reputation: 15239

as for C# 9, we can use Recods

public sealed record LogCategory(string Value)
{
    public static readonly LogCategory Trace   = new("Trace");
    public static readonly LogCategory Debug   = new("Debug");
    public static readonly LogCategory Info    = new("Info");
    public static readonly LogCategory Warning = new("Warning");
    public static readonly LogCategory Error   = new("Error");

    public override string ToString() => Value;
}

Upvotes: 0

Bugs Bunny
Bugs Bunny

Reputation: 27

This is a pretty basic way of achieving what you want. I am sure it can be optimized. The class could be a struct, for instance, and the foreach probably could be faster as a for loop.

public enum MyEnum
{
    First,
    Last
}
public class StringEnum<TEnum> : Dictionary<TEnum, string> 
    where TEnum : System.Enum 
{
    public StringEnum( params (TEnum Key, string Value) [] enumValues) 
    {
        foreach(var v in enumValues) base.Add(v.Key, v.Value);
    }
    public void Add(TEnum Key, string Value)=>base.Add(Key, Value);
    public string this[TEnum key]=>base[key];
}

…then you can access it via…

var se=new StringEnum<MyEnum>( (MyEnum.First, "Bugs"), (MyEnum.Last, "Bunny") );
Console.WriteLine(se[MyEnum.First]);        

Upvotes: 0

Jim Mischel
Jim Mischel

Reputation: 134075

Have you considered a lookup table using a Dictionary?

enum GroupTypes
{
    TheGroup,
    TheOtherGroup
}

Dictionary<string, GroupTypes> GroupTypeLookup = new Dictionary<string, GroupTypes>();
// initialize lookup table:
GroupTypeLookup.Add("OEM", TheGroup);
GroupTypeLookup.Add("CMB", TheOtherGroup);

You can then use GroupTypeLookup.TryGetValue() to look up a string when you read it.

Upvotes: 6

Michael K
Michael K

Reputation: 13

Our team utilizes SignalR to deliver messages to our front end. We found that adding this to the Startup.cs file solved our issue:

           services.AddSignalR()
            .AddJsonProtocol(options => {
                options.PayloadSerializerOptions.Converters.Add(new JsonStringEnumConverter());
            })

Enums are now converted to strings instead of ints.

Upvotes: -2

Frederik van Lierde
Frederik van Lierde

Reputation: 66

Several good answers above if you like to code the extension yourself

I use CodeHelper.Core.Extensions

enum GroupTypes
{

    [StringValue("OEM")] TheGroup,
    [StringValue("CMB")] TheOtherGroup = "CMB"
}

GroupTypes.TheOtherGroup.ToStringValue()

If you don't have a StringValue Attribute added to the values, the extension returns the normal name (.ToString()). And it's super easy to add spaces and other normally not-allowed characters like spaces or starting with numbers.

Upvotes: 3

Werymag
Werymag

Reputation: 31

I think the best way use Dictionary <Enum, string> with extension method. It's simple and clear.

Enum

public enum GroupTypes
{
    TheGroup,
    TheOtherGroup
}

Extension

public static class GroupTypesExtensions
{
    private static Dictionary<GroupTypes, string> Descriptions =
         new Dictionary<GroupTypes, string>
         {
                { GroupTypes.TheGroup,"Description Group 1" },
                { GroupTypes.TheOtherGroup, "Description Group 2" }

         };

    public static string Description(this GroupTypes value)
    {
        return Descriptions[value];
    }
}

Use

GroupTypes.TheOtherGroup.Description();
GroupTypes.TheGroup.Description();

Upvotes: 3

Pawel Cioch
Pawel Cioch

Reputation: 3194

Based on https://stackoverflow.com/a/1343517/1818723 I came up with an enum with TryParse method

public class FancyStringEnum
{
    private FancyStringEnum(string value) { Value = value; }

    public string Value { get; private set; }

    private static List<FancyStringEnum> choices = new List<FancyStringEnum>
    {
        new FancyStringEnum("Small") ,
        new FancyStringEnum("Big Thing") ,
        new FancyStringEnum("Value with Spaces")
    };

    public static FancyStringEnum Small { get { return choices[0]; } }
    public static FancyStringEnum BigThing { get { return choices[1]; } }
    public static FancyStringEnum ValueWithSpaces { get { return choices[2]; } }

    public override string ToString()
    {
        return Value;
    }

    public static bool TryParse(string value, bool ignoreCase, out FancyStringEnum result)
    {
        var sc = StringComparison.InvariantCulture;
        if (ignoreCase)
            sc = StringComparison.InvariantCultureIgnoreCase;

        foreach (var choice in choices)
        {

            if (choice.Value.Equals(value, sc))
            {
                result = choice;
                return true;
            }
        }

        result = new FancyStringEnum(null);
        return false;
    }

    public static FancyStringEnum Parse(string value, bool ignoreCase)
    {
        var sc = StringComparison.InvariantCulture;
        if (ignoreCase)
            sc = StringComparison.InvariantCultureIgnoreCase;

        foreach (var choice in choices)
        {

            if (choice.Value.Equals(value, sc))
            {
                return choice;
            }
        }

        return new FancyStringEnum(null);
    }
}

Pass in type-safe string values as a parameter:

public static void Do(string message, FancyStringEnum value)
{
    if (value == FancyStringEnum.Small)
    {
        //do something
    } else if (value == FancyStringEnum.BigThing)
    {
        //do something else
    }
}

TryParse and Parse in action:

string something = "something"; //substiture with "small" to see it parsed 
if (FancyStringEnum.TryParse(something, true, out var se))
    Console.WriteLine(se.Value);
else
    Console.WriteLine($"unable to parse {something}");

//or    

var v2 = FancyStringEnum.Parse(something, true);
if (v2.Value == null)
    Console.WriteLine($"unable to parse {something}");
else
    Console.WriteLine(v2.Value); //do something with parsed enum

    

Could probably extract a base class to create StringEnums with less code

Upvotes: 0

Even Mien
Even Mien

Reputation: 45928

I like to use properties in a class instead of methods, since they look more enum-like.

Here's an example for a Logger:

public class LogCategory
{
    private LogCategory(string value) { Value = value; }

    public string Value { get; private set; }

    public static LogCategory Trace   { get { return new LogCategory("Trace"); } }
    public static LogCategory Debug   { get { return new LogCategory("Debug"); } }
    public static LogCategory Info    { get { return new LogCategory("Info"); } }
    public static LogCategory Warning { get { return new LogCategory("Warning"); } }
    public static LogCategory Error   { get { return new LogCategory("Error"); } }

    public override string ToString()
    {
        return Value;
    }
}

Pass in type-safe string values as a parameter:

public static void Write(string message, LogCategory logCategory)
{
    var log = new LogEntry { Message = message };
    Logger.Write(log, logCategory.Value);
}

Usage:

Logger.Write("This is almost like an enum.", LogCategory.Info);

Upvotes: 686

I am sharing it for a different answer.I want to send a string in return for a string. For example Airport = A, Railway = R.

public enum LocationType
    {
        AIRPORT = 1,
        RAILWAY = 2,
        DOWNTOWN = 3
    }
    
public enum ShortLocationType
    {
        A = 1,
        R = 2,
        D = 3
    }

((ShortLocationType)(int)Enum.Parse(typeof(LocationType), "AIRPORT")).ToString();

Output "A"

((ShortLocationType)(int)Enum.Parse(typeof(LocationType), "DOWNTOWN")).ToString();

Output "D"

Upvotes: 0

Adamo Branz
Adamo Branz

Reputation: 184

If not all the values of your enum actually have a string and if you want to set those values later, I use classes like this below:

 public class SessionResoult
{
    public enum SessionResoultType
    {
        Success,
        Error,
    }
    public SessionResoult(SessionResoultType sesionResoultType, string value = null)
    {
        Type = sesionResoultType;
        Value = value;
       
    }

    public SessionResoultType Type { get; set; }

    public string Value { get; private set; }
  

    public sealed class Success : SessionResoult
    {
        public Success() : base(SessionResoultType.Success) { }
    }

    public sealed class Error : SessionResoult
    {
        public Error(string value) : base(SessionResoultType.Error, value) { }
    }

    public override string ToString()
    {
        if(this is Success)
        {
            return (SessionResoultType.Success.ToString());
        }else if(this is Error)
        {
            return $"{SessionResoultType.Error}:{this.Value}";
        }
        else { return base.ToString(); }
    }

}

Usage example:

private SessionResoult ok = new SessionResoult.Success(); private SessionResoult error = new SessionResoult.Error("No network available");

Upvotes: 0

Rolf Staflin
Rolf Staflin

Reputation: 2197

Here is my take on this, using C# 9.0 syntax to keep it clean. I define a base class for the enums:

public class StringEnum
{
    protected StringEnum(string value) { Value = value; }
    public string Value { get; }
    public override string ToString() => Value;
}

Creating new enum style types is then easy and compact:

public class GroupTypes : StringEnum
{ 
    private GroupTypes(string value) : base(value) {}

    public static readonly GroupTypes TheGroup = new("OEM");
    public static readonly GroupTypes TheOtherGroup = new("CMB");
}

Use it like this:

void Example(GroupTypes groupType)
{
    Console.WriteLine(groupType); // Will print "OEM" or "CMB"
    if (groupType == GroupTypes.TheGroup) { ... }
}

You can also add more functionality to StringEnum, which will then be available for all your subclasses (e. g., implementing IComparable and overriding Equals and GetHashCode)

Upvotes: 4

moldypenguins
moldypenguins

Reputation: 509

Taken from @EvenMien and added in some of the comments. (Also for my own use case)

public struct AgentAction
{
    private AgentAction(string value) { Value = value; }

    public string Value { get; private set; }

    public override string ToString() { return this.Value; }
    
    public static AgentAction Login = new AgentAction("Login");
    public static AgentAction Logout = new AgentAction("Logout");

    public static implicit operator string(AgentAction action) { return action.ToString(); }
}

Upvotes: 9

Why not just use the same enum, but just call .ToString()?

using System;

public class EnumSample
{
    enum Holidays
    {
        Christmas = 1,
        Easter = 2
    };

    public static void Main()
    {
        Enum myHolidays = Holidays.Christmas;
        Console.WriteLine("The value of this instance is '{0}'", myHolidays.ToString());
    }
}

Upvotes: 6

Scott
Scott

Reputation: 1119

I used a structure as alluded to in a previous answer, but did away with any complexity. To me, this was most like creating an enumeration of strings. It is used in the same manner that an enumeration is used.

    struct ViewTypes
    {
        public const string View1 = "Whatever string you like";
        public const string View2 = "another string";
    }

Example use:

   switch( some_string_variable )
   {
      case ViewTypes.View1: /* do something */ break;
      case ViewTypes.View2: /* do something else */ break;
   }

Upvotes: 80

rpattabi
rpattabi

Reputation: 10217

How about using a static class with constants?

static class GroupTypes
{
  public const string TheGroup = "OEM";
  public const string TheOtherGroup = "CMB";
}

void DoSomething(string groupType)
{
  if(groupType == GroupTypes.TheGroup)
  {
    // Be nice
  }  
  else if (groupType == GroupTypes.TheOtherGroup)
  {
    // Continue to be nice
  }
  else
  {
    // unexpected, throw exception?
  }
}

Upvotes: 186

user3180664
user3180664

Reputation: 315

New in .Net Core 3.0/C# 8.0 (if your work environment allows you to upgrade your project) is a short-hand switch statement that looks somewhat enum-ish. At the end of the day it's the same old boring switch statement we've been using for years.

Only real difference here is that the switch statement got a new suit.

public static RGBColor FromRainbow(Rainbow colorBand) =>
colorBand switch
{
    Rainbow.Red    => new RGBColor(0xFF, 0x00, 0x00),
    Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),
    Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),
    Rainbow.Green  => new RGBColor(0x00, 0xFF, 0x00),
    Rainbow.Blue   => new RGBColor(0x00, 0x00, 0xFF),
    Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),
    Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),
    _              => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
};

You'll notice that the code above which I copied from here, is actually using an enum as a param.

It's not exactly what you want (and trust me, I've wanted something of similar to what the OP is requesting for a long time), but I actually feel like this is somewhat of an olive branch from MS. JMO.

Hope it helps someone!

Upvotes: 11

nyconing
nyconing

Reputation: 1136

Adding this class

public class DatabasePreference {
    public DatabasePreference([CallerMemberName] string preferenceName = "") {
        PreferenceName = preferenceName;
    }
    public string PreferenceName;
}

This work is using CallerMemberName to minimize the coding

Using:

//Declare names
public static DatabasePreference ScannerDefaultFlashLight = new DatabasePreference();
public static DatabasePreference ScannerQrCodes = new DatabasePreference();
public static DatabasePreference Scanner1dCodes = new DatabasePreference();

Test it:

Console.WriteLine(ScannerDefaultFlashLight.PreferenceName);
Console.WriteLine(ScannerDefaultFlashLight.Scanner1dCodes);

output:

ScannerDefaultFlashLight
Scanner1dCodes

Upvotes: 1

darasd
darasd

Reputation: 2987

Try adding constants to a static class. You don't end up with a Type, but you will have readable, organised constants:

public static class GroupTypes {

    public const string TheGroup = "OEM";
    public const string TheOtherGroup = "CMB";

}

Upvotes: 50

Lomithrani
Lomithrani

Reputation: 2177

Following the answer of @Even Mien I have tried to go a bit further and make it Generic, I seem to be almost there but one case still resist and I probably can simplify my code a bit.
I post it here if anyone see how I could improve and especially make it works as I can't assign it from a string

So Far I have the following results:

        Console.WriteLine(TestEnum.Test1);//displays "TEST1"

        bool test = "TEST1" == TestEnum.Test1; //true

        var test2 = TestEnum.Test1; //is TestEnum and has value

        string test3 = TestEnum.Test1; //test3 = "TEST1"

        var test4 = TestEnum.Test1 == TestEnum.Test2; //false
         EnumType<TestEnum> test5 = "TEST1"; //works fine

        //TestEnum test5 = "string"; DOESN'T compile .... :(:(

Where the magics happens :

public abstract  class EnumType<T>  where T : EnumType<T>   
{

    public  string Value { get; set; }

    protected EnumType(string value)
    {
        Value = value;
    }


    public static implicit operator EnumType<T>(string s)
    {
        if (All.Any(dt => dt.Value == s))
        {
            Type t = typeof(T);

            ConstructorInfo ci = t.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,null, new Type[] { typeof(string) }, null);

            return (T)ci.Invoke(new object[] {s});
        }
        else
        {
            return null;
        }
    }

    public static implicit operator string(EnumType<T> dt)
    {
        return dt?.Value;
    }


    public static bool operator ==(EnumType<T> ct1, EnumType<T> ct2)
    {
        return (string)ct1 == (string)ct2;
    }

    public static bool operator !=(EnumType<T> ct1, EnumType<T> ct2)
    {
        return !(ct1 == ct2);
    }


    public override bool Equals(object obj)
    {
        try
        {
            return (string)obj == Value;
        }
        catch
        {
            return false;
        }
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public static IEnumerable<T> All
     => typeof(T).GetProperties()
       .Where(p => p.PropertyType == typeof(T))
       .Select(x => (T)x.GetValue(null, null));



}

I only then have to declare this for my enums:

public class TestEnum : EnumType<TestEnum> 
{

    private TestEnum(string value) : base(value)
    {}

    public static TestEnum Test1 { get { return new TestEnum("TEST1"); } }
    public static TestEnum Test2 { get { return new TestEnum("TEST2"); } }
}

Upvotes: 3

Siavash Mortazavi
Siavash Mortazavi

Reputation: 1862

I wanted to avoid using string literals completely, and also I didn't need to have space in item descriptions. More importantly, I wanted to have a mechanism to check if the provided string is a valid item, so I came up with this solution:

public class Seasons
{
    public static string Spring { get; }
    public static string Summer { get; }
    public static string Fall { get; }
    public static string Winter { get; }

    public static bool IsValid(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            return false;
        }

        try
        {           
            return typeof(Seasons).GetProperty(propertyName) != null;
        }
        catch
        {
            return false;
        }       
    }
}

And here is how it works:

void Main()
{
    string s = nameof(Seasons.Fall);
    Console.WriteLine($"Fall is valid: {Seasons.IsValid(s)}"); // true

    s = "WrongSeason";
    Console.WriteLine($"WrongSeason is valid: {Seasons.IsValid(s)}"); // false
}

I tried to refactor IsValid() into a base class and use reflection to read the type (MethodBase.GetCurrentMethod().DeclaringType), but since I wanted to have it static, it returns the base class type, not the inherited type. Your remedy to this will be very welcomed! Here is what I was trying to achieve:

public  class Seasons : ConstantStringsBase
{
    // ... same
}

public  class ConstantStringsBase
{
    public static bool IsValid(string propertyName)
    {       
        return MethodBase.GetCurrentMethod().DeclaringType.GetProperty(propertyName) != null;
    }
}

Upvotes: 2

Glennular
Glennular

Reputation: 18225

You could also use the extension model:

public enum MyEnum
{
    [Description("String 1")]
    V1= 1,
    [Description("String 2")]
    V2= 2
} 

Your Extension Class

public static class MyEnumExtensions
{
    public static string ToDescriptionString(this MyEnum val)
    {
        DescriptionAttribute[] attributes = (DescriptionAttribute[])val
           .GetType()
           .GetField(val.ToString())
           .GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : string.Empty;
    }
} 

usage:

MyEnum myLocal = MyEnum.V1;
print(myLocal.ToDescriptionString());

Upvotes: 297

Mahib
Mahib

Reputation: 4063

I've done something like this;

public enum BusinessUnits
{
    NEW_EQUIPMENT = 0,
    USED_EQUIPMENT = 1,
    RENTAL_EQUIPMENT = 2,
    PARTS = 3,
    SERVICE = 4,
    OPERATOR_TRAINING = 5
}

public class BusinessUnitService
{
    public static string StringBusinessUnits(BusinessUnits BU)
    {
        switch (BU)
        {
            case BusinessUnits.NEW_EQUIPMENT: return "NEW EQUIPMENT";
            case BusinessUnits.USED_EQUIPMENT: return "USED EQUIPMENT";
            case BusinessUnits.RENTAL_EQUIPMENT: return "RENTAL EQUIPMENT";
            case BusinessUnits.PARTS: return "PARTS";
            case BusinessUnits.SERVICE: return "SERVICE";
            case BusinessUnits.OPERATOR_TRAINING: return "OPERATOR TRAINING";
            default: return String.Empty;
        }
    }
}

Call it with this;

BusinessUnitService.StringBusinessUnits(BusinessUnits.PARTS)

Upvotes: 0

Roman M
Roman M

Reputation: 588

public class DataType
{
    private readonly string value;
    private static readonly Dictionary<string, DataType> predefinedValues;

    public static readonly DataType Json = new DataType("json");
    public static readonly DataType Xml = new DataType("xml");
    public static readonly DataType Text = new DataType("text");
    public static readonly DataType Html = new DataType("html");
    public static readonly DataType Binary = new DataType("binary");

    static DataType()
    {
        predefinedValues = new Dictionary<string, DataType>();
        predefinedValues.Add(Json.Value, Json);
        predefinedValues.Add(Xml.Value, Xml);
        predefinedValues.Add(Text.Value, Text);
        predefinedValues.Add(Html.Value, Html);
        predefinedValues.Add(Binary.Value, Binary);
    }

    private DataType(string value)
    {
        this.value = value;
    }

    public static DataType Parse(string value)
    {
        var exception = new FormatException($"Invalid value for type {nameof(DataType)}");
        if (string.IsNullOrEmpty(value))
            throw exception;

        string key = value.ToLower();
        if (!predefinedValues.ContainsKey(key))
            throw exception;

        return predefinedValues[key];
    }

    public string Value
    {
        get { return value; }
    }
}

Upvotes: 4

ThinkBonobo
ThinkBonobo

Reputation: 16535

I was basically looking for the Reflection answer by @ArthurC

Just to extend his answer a little bit, you can make it even better by having a generic function:

    // If you want for a specific Enum
    private static string EnumStringValue(GroupTypes e)
    {
        return EnumStringValue<GroupTypes>(e);
    }

    // Generic
    private static string EnumStringValue<T>(T enumInstance)
    {
        return Enum.GetName(typeof(T), enumInstance);
    } 

Then you can just wrap whatever you have

EnumStringValue(GroupTypes.TheGroup) // if you incorporate the top part

or

EnumStringValue<GroupTypes>(GroupTypes.TheGroup) // if you just use the generic

Upvotes: 1

Luis Orantes
Luis Orantes

Reputation: 437

Another way to deal with the problem, is to have a enum and a array of strings that will map the enum values with the list of strings:

public enum GroupTypes
{
    TheGroup  = 0,
    TheOtherGroup 
}

string[] GroupTypesStr = {
    "OEM",
    "CMB"
};

you may use it something like this:

Log.Write(GroupTypesStr[(int)GroupTypes.TheOtherGroup]);

It will prompt CMB

PROS:

  1. Easy and clean code.
  2. High Performance (specially in comparison with those approaches that uses classes)

CONS:

  1. Prone to mess up the list when editing it, but it will be okay for a short list.

Upvotes: 15

Mike
Mike

Reputation: 1683

A small tweak to Glennular Extension method, so you could use the extension on other things than just ENUM's;

using System;
using System.ComponentModel;
namespace Extensions {
    public static class T_Extensions {
        /// <summary>
        /// Gets the Description Attribute Value
        /// </summary>
        /// <typeparam name="T">Entity Type</typeparam>
        /// <param name="val">Variable</param>
        /// <returns>The value of the Description Attribute or an Empty String</returns>
        public static string Description<T>(this T t) {
            DescriptionAttribute[] attributes = (DescriptionAttribute[])t.GetType().GetField(t.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : string.Empty;
        }
    }
}

Or Using Linq

using System;
using System.ComponentModel;
using System.Linq;

namespace Extensions {


public static class T_Extensions {
        public static string Description<T>(this T t) =>
            ((DescriptionAttribute[])t
            ?.GetType()
            ?.GetField(t?.ToString())
            ?.GetCustomAttributes(typeof(DescriptionAttribute), false))
            ?.Select(a => a?.Description)
            ?.FirstOrDefault() 
            ?? string.Empty;  
    }
}

Upvotes: 3

C. Ross
C. Ross

Reputation: 31868

Use a class.

Edit: Better example

class StarshipType
{
    private string _Name;
    private static List<StarshipType> _StarshipTypes = new List<StarshipType>();

    public static readonly StarshipType Ultralight = new StarshipType("Ultralight");
    public static readonly StarshipType Light = new StarshipType("Light");
    public static readonly StarshipType Mediumweight = new StarshipType("Mediumweight");
    public static readonly StarshipType Heavy = new StarshipType("Heavy");
    public static readonly StarshipType Superheavy = new StarshipType("Superheavy");

    public string Name
    {
        get { return _Name; }
        private set { _Name = value; }
    }

    public static IList<StarshipType> StarshipTypes
    {
        get { return _StarshipTypes; }
    }

    private StarshipType(string name, int systemRatio)
    {
        Name = name;
        _StarshipTypes.Add(this);
    }

    public static StarshipType Parse(string toParse)
    {
        foreach (StarshipType s in StarshipTypes)
        {
            if (toParse == s.Name)
                return s;
        }
        throw new FormatException("Could not parse string.");
    }
}

Upvotes: 16

toddmo
toddmo

Reputation: 22446

You can use two enums. One for the database and the other for readability.

You just need to make sure they stay in sync, which seems like a small cost. You don't have to set the values, just set the positions the same, but setting the values makes it very clear the two enums are related and prevents errors from rearranging the enum members. And a comment lets the maintenance crew know these are related and must be kept in sync.

// keep in sync with GroupTypes
public enum GroupTypeCodes
{
    OEM,
    CMB
}

// keep in sync with GroupTypesCodes
public enum GroupTypes
{
    TheGroup = GroupTypeCodes.OEM,
    TheOtherGroup = GroupTypeCodes.CMB
}

To use it you just convert to the code first:

GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = ((GroupTypeCodes)myGroupType).ToString();

Then if you want to make it even more convenient you can add an extension function that only works for this type of enum:

public static string ToString(this GroupTypes source)
{
    return ((GroupTypeCodes)source).ToString();
}

and you can then just do:

GroupTypes myGroupType = GroupTypes.TheGroup;
string valueToSaveIntoDatabase = myGroupType.ToString();

Upvotes: 1

Nicolas Bodin
Nicolas Bodin

Reputation: 1591

This is a way to use it as a strongly typed parameter or as a string :

public class ClassLikeEnum
{
    public string Value
    {
        get;
        private set;
    }

    ClassLikeEnum(string value) 
    {
        Value = value;
    }

    public static implicit operator string(ClassLikeEnum c)
    {
        return c.Value;
    }

    public static readonly ClassLikeEnum C1 = new ClassLikeEnum("RandomString1");
    public static readonly ClassLikeEnum C2 = new ClassLikeEnum("RandomString2");
}

Upvotes: 3

Claus Elmann
Claus Elmann

Reputation: 95

In VS 2015, you can use nameof

public class LogCategory
{
    public static string Trace;
    public static string Debug;
    public static string Info;
    public static string Warning;
    public static string Error;
}

Usage:

Logger.Write("This is almost like an enum.", nameof(LogCategory.Info));

Upvotes: 3

Related Questions