How to define an enum with string value?

后端 未结 18 1377
一生所求
一生所求 2020-12-12 14:53

I am trying to define an Enum and add valid common separators which used in CSV or similar files. Then I am going to bind it to a ComboBox as a dat

相关标签:
18条回答
  • 2020-12-12 15:05

    Building on some of the answers here I have implemented a reusable base class that mimics the behaviour of an enum but with string as the underlying type. It supports various operations including:

    1. getting a list of possible values
    2. converting to string
    3. comparison with other instances via .Equals, ==, and !=
    4. conversion to/from JSON using a JSON.NET JsonConverter

    This is the base class in it's entirety:

    public abstract class StringEnumBase<T> : IEquatable<T>
        where T : StringEnumBase<T>
    {
        public string Value { get; }
    
        protected StringEnumBase(string value) => this.Value = value;
    
        public override string ToString() => this.Value;
    
        public static List<T> AsList()
        {
            return typeof(T)
                .GetProperties(BindingFlags.Public | BindingFlags.Static)
                .Where(p => p.PropertyType == typeof(T))
                .Select(p => (T)p.GetValue(null))
                .ToList();
        }
    
        public static T Parse(string value)
        {
            List<T> all = AsList();
    
            if (!all.Any(a => a.Value == value))
                throw new InvalidOperationException($"\"{value}\" is not a valid value for the type {typeof(T).Name}");
    
            return all.Single(a => a.Value == value);
        }
    
        public bool Equals(T other)
        {
            if (other == null) return false;
            return this.Value == other?.Value;
        }
    
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (obj is T other) return this.Equals(other);
            return false;
        }
    
        public override int GetHashCode() => this.Value.GetHashCode();
    
        public static bool operator ==(StringEnumBase<T> a, StringEnumBase<T> b) => a?.Equals(b) ?? false;
    
        public static bool operator !=(StringEnumBase<T> a, StringEnumBase<T> b) => !(a?.Equals(b) ?? false);
    
        public class JsonConverter<T> : Newtonsoft.Json.JsonConverter
            where T : StringEnumBase<T>
        {
            public override bool CanRead => true;
    
            public override bool CanWrite => true;
    
            public override bool CanConvert(Type objectType) => ImplementsGeneric(objectType, typeof(StringEnumBase<>));
    
            private static bool ImplementsGeneric(Type type, Type generic)
            {
                while (type != null)
                {
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == generic)
                        return true;
    
                    type = type.BaseType;
                }
    
                return false;
            }
    
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                JToken item = JToken.Load(reader);
                string value = item.Value<string>();
                return StringEnumBase<T>.Parse(value);
            }
    
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                if (value is StringEnumBase<T> v)
                    JToken.FromObject(v.Value).WriteTo(writer);
            }
        }
    }
    

    And this is how you would implement your "string enum":

    [JsonConverter(typeof(JsonConverter<Colour>))]
    public class Colour : StringEnumBase<Colour>
    {
        private Colour(string value) : base(value) { }
    
        public static Colour Red => new Colour("red");
        public static Colour Green => new Colour("green");
        public static Colour Blue => new Colour("blue");
    }
    

    Which could be used like this:

    public class Foo
    {
        public Colour colour { get; }
    
        public Foo(Colour colour) => this.colour = colour;
    
        public bool Bar()
        {
            if (this.colour == Colour.Red || this.colour == Colour.Blue)
                return true;
            else
                return false;
        }
    }
    

    I hope someone finds this useful!

    0 讨论(0)
  • 2020-12-12 15:05

    Enumaration Class

     public sealed class GenericDateTimeFormatType
        {
    
            public static readonly GenericDateTimeFormatType Format1 = new GenericDateTimeFormatType("dd-MM-YYYY");
            public static readonly GenericDateTimeFormatType Format2 = new GenericDateTimeFormatType("dd-MMM-YYYY");
    
            private GenericDateTimeFormatType(string Format)
            {
                _Value = Format;
            }
    
            public string _Value { get; private set; }
        }
    

    Enumaration Consuption

    public static void Main()
    {
           Country A = new Country();
    
           A.DefaultDateFormat = GenericDateTimeFormatType.Format1;
    
          Console.ReadLine();
    }
    
    0 讨论(0)
  • 2020-12-12 15:06

    For a simple enum of string values (or any other type):

    public static class MyEnumClass
    {
        public const string 
            MyValue1 = "My value 1",
            MyValue2 = "My value 2";
    }
    

    Usage: string MyValue = MyEnumClass.MyValue1;

    0 讨论(0)
  • 2020-12-12 15:07

    A class that emulates enum behaviour but using string instead of int can be created as follows...

    public class GrainType
    {
        private string _typeKeyWord;
    
        private GrainType(string typeKeyWord)
        {
            _typeKeyWord = typeKeyWord;
        }
    
        public override string ToString()
        {
            return _typeKeyWord;
        }
    
        public static GrainType Wheat = new GrainType("GT_WHEAT");
        public static GrainType Corn = new GrainType("GT_CORN");
        public static GrainType Rice = new GrainType("GT_RICE");
        public static GrainType Barley = new GrainType("GT_BARLEY");
    
    }
    

    Usage...

    GrainType myGrain = GrainType.Wheat;
    
    PrintGrainKeyword(myGrain);
    

    then...

    public void PrintGrainKeyword(GrainType grain) 
    {
        Console.Writeline("My Grain code is " + grain.ToString());   // Displays "My Grain code is GT_WHEAT"
    }
    
    0 讨论(0)
  • 2020-12-12 15:08

    Well first you try to assign strings not chars, even if they are just one character. use ',' instead of ",". Next thing is, enums only take integral types without char you could use the unicode value, but i would strongly advice you not to do so. If you are certain that these values stay the same, in differnt cultures and languages, i would use a static class with const strings.

    0 讨论(0)
  • 2020-12-12 15:08

    It works for me..

       public class ShapeTypes
        {
            private ShapeTypes() { }
            public static string OVAL
            {
                get
                {
                    return "ov";
                }
                private set { }
            }
    
            public static string SQUARE
            {
                get
                {
                    return "sq";
                }
                private set { }
            }
    
            public static string RECTANGLE
            {
                get
                {
                    return "rec";
                }
                private set { }
            }
        }
    
    0 讨论(0)
提交回复
热议问题