How to define an enum with string value?

后端 未结 18 1379
一生所求
一生所求 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:18

    It is kind of late for answer, but maybe it helps someone in future. I found it easier to use struct for this kind of problem.

    Following sample is copy pasted part from MS code:

    namespace System.IdentityModel.Tokens.Jwt
    {
        //
        // Summary:
        //     List of registered claims from different sources http://tools.ietf.org/html/rfc7519#section-4
        //     http://openid.net/specs/openid-connect-core-1_0.html#IDToken
        public struct JwtRegisteredClaimNames
        {
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Actort = "actort";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Typ = "typ";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Sub = "sub";
            //
            // Summary:
            //     http://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
            public const string Sid = "sid";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Prn = "prn";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Nbf = "nbf";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string Nonce = "nonce";
            //
            // Summary:
            //     http://tools.ietf.org/html/rfc7519#section-4
            public const string NameId = "nameid";
    
        }
    }
    
    0 讨论(0)
  • 2020-12-12 15:21

    As far as I know, you will not be allowed to assign string values to enum. What you can do is create a class with string constants in it.

    public static class SeparatorChars
    {
        public static String Comma { get { return ",";} } 
        public static String Tab { get { return "\t,";} } 
        public static String Space { get { return " ";} } 
    }
    
    0 讨论(0)
  • 2020-12-12 15:24

    We can't define enumeration as string type. The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.

    If you need more details on enumeration please follow below link,that link will help you to understand enumeration. Enumeration

    @narendras1414

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

    While it is really not possible to use a char or a string as the base for an enum, i think this is not what you really like to do.

    Like you mentioned you'd like to have an enum of possibilities and show a string representation of this within a combo box. If the user selects one of these string representations you'd like to get out the corresponding enum. And this is possible:

    First we have to link some string to an enum value. This can be done by using the DescriptionAttribute like it is described here or here.

    Now you need to create a list of enum values and corresponding descriptions. This can be done by using the following method:

    /// <summary>
    /// Creates an List with all keys and values of a given Enum class
    /// </summary>
    /// <typeparam name="T">Must be derived from class Enum!</typeparam>
    /// <returns>A list of KeyValuePair&lt;Enum, string&gt; with all available
    /// names and values of the given Enum.</returns>
    public static IList<KeyValuePair<T, string>> ToList<T>() where T : struct
    {
        var type = typeof(T);
    
        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be an enum");
        }
    
        return (IList<KeyValuePair<T, string>>)
                Enum.GetValues(type)
                    .OfType<T>()
                    .Select(e =>
                    {
                        var asEnum = (Enum)Convert.ChangeType(e, typeof(Enum));
                        return new KeyValuePair<T, string>(e, asEnum.Description());
                    })
                    .ToArray();
    }
    

    Now you'll have a list of key value pairs of all enums and their description. So let's simply assign this as a data source for a combo box.

    var comboBox = new ComboBox();
    comboBox.ValueMember = "Key"
    comboBox.DisplayMember = "Value";
    comboBox.DataSource = EnumUtilities.ToList<Separator>();
    
    comboBox.SelectedIndexChanged += (sender, e) =>
    {
        var selectedEnum = (Separator)comboBox.SelectedValue;
        MessageBox.Show(selectedEnum.ToString());
    }
    

    The user sees all the string representations of the enum and within your code you'll get the desired enum value.

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

    I created a base class for creating string-valued enums in .NET. It is just one C# file that you can copy & paste into your projects, or install via NuGet package named StringEnum.

    Usage:

    ///<completionlist cref="HexColor"/> 
    class HexColor : StringEnum<HexColor>
    {
        public static readonly HexColor Blue = New("#FF0000");
        public static readonly HexColor Green = New("#00FF00");
        public static readonly HexColor Red = New("#000FF");
    }
    

    Features

    • Your StringEnum looks somewhat similar to a regular enum:
        // Static Parse Method
        HexColor.Parse("#FF0000") // => HexColor.Red
        HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
        HexColor.Parse("invalid") // => throws InvalidOperationException
    
        // Static TryParse method.
        HexColor.TryParse("#FF0000") // => HexColor.Red
        HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
        HexColor.TryParse("invalid") // => null
    
        // Parse and TryParse returns the preexistent instances
        object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true
    
        // Conversion from your `StringEnum` to `string`
        string myString1 = HexColor.Red.ToString(); // => "#FF0000"
        string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)
    
    • Intellisense will suggest the enum name if the class is annotated with the xml comment <completitionlist>. (Works in both C# and VB): i.e.

    Intellisense demo

    Instalation

    Either:

    • Install latest StringEnum NuGet package, which is based on .Net Standard 1.0 so it runs on .Net Core >= 1.0, .Net Framework >= 4.5, Mono >= 4.6, etc.
    • Or paste the following StringEnum base class to your project. (latest version)
        public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
        {
            protected string Value;
            private static IList<T> valueList = new List<T>();
            protected static T New(string value)
            {
                if (value == null)
                    return null; // the null-valued instance is null.
    
                var result = new T() { Value = value };
                valueList.Add(result);
                return result;
            }
    
            public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
            public override string ToString() => Value;
    
            public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
            public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;
    
            public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
            bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
            public override int GetHashCode() => Value.GetHashCode();
    
            /// <summary>
            /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
            /// </summary>
            /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
            /// <param name="caseSensitive">If true, the strings must match case sensitivity.</param>
            public static T Parse(string value, bool caseSensitive = false)
            {
                var result = TryParse(value, caseSensitive);
                if (result == null)
                    throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");
    
                return result;
            }
    
            /// <summary>
            /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
            /// </summary>
            /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
            /// <param name="caseSensitive">If true, the strings must match case sensitivity.</param>
            public static T TryParse(string value, bool caseSensitive = false)
            {
                if (value == null) return null;
                if (valueList.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
                var field = valueList.FirstOrDefault(f => f.Value.Equals(value,
                        caseSensitive ? StringComparison.Ordinal
                                      : StringComparison.OrdinalIgnoreCase));
                // Not using InvariantCulture because it's only supported in NETStandard >= 2.0
    
                if (field == null)
                    return null;
    
                return field;
            }
        }
    
    • For Newtonsoft.Json serialization support, copy this extended version instead. StringEnum.cs

    I realized after the fact that this code is similar to Ben's answer. I sincerely wrote it from scratch. However I think it has a few extras, like the <completitionlist> hack, the resulting class looks more like an Enum, no use of reflection on Parse(), the NuGet package and repo where I will hopefully address incoming issues and feedback.

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

    What I have recently begun doing is using Tuples

    public static (string Fox, string Rabbit, string Horse) Animals = ("Fox", "Rabbit", "Horse");
    ...
    public static (string Comma, string Tab, string Space) SeparatorChars = (",", "\t", " ");
    
    0 讨论(0)
提交回复
热议问题