简体   繁体   English

字符串枚举自定义类 <T> 与带有属性C#的枚举

[英]String Enum custom class<T> vs Enum with attributes C#

After investigating I concluded what string Enum with attributes is too slow and inconvenient for my purposes. 经过调查后,我得出结论,对于我的目的,带有属性的字符串Enum太慢且不方便。

So my question - is my implementation normal or way redundant and dangerous?=) 所以我的问题-我的实现是正常的还是冗余且危险的?=)

public class StringEnum<TChildType> where TChildType: StringEnum<TChildType>, new()
{            
     private readonly Type childType;
     private string _value;
     private readonly HashSet<string> members;

     public string Value
     {
        get { return _value; }
        set
        {
            if (!Contains(value))
                {
                    throw new NotImplementedException(String.Format("Value '{0}' wasnt found in Enum", value));
                }
                _value = value;
            }
        }

        public IEnumerable<string> Values
        {
            get { return members; }
        }
        public bool Contains(string value)
        {
            return members.Contains(value);
        }

        public static IEnumerable<string> GetValues()
        {
            return Service.GetGenericConstProperties<string>(typeof(TChildType));
        }

        public StringEnum()
        {
            childType = typeof(TChildType);
            members = Service.GetGenericStaticProperties<string>(childType).ToHashSet();
            if (members.Count < 2) throw new Exception("Fill Enum!");               
        }

        public static implicit operator StringEnum<TChildType>(string str)
        {
            return new TChildType { Value = str };
        }

        public static implicit operator string(StringEnum<TChildType> source)
        {
            return source != null ? source.Value : null;
        }
    }

Enum Example: 枚举示例:

public class PrinterType : StringEnum<PrinterType>
{
   public const string CommonPrinter = "... ...";
   .....
}

How to use: 如何使用:

public class MyPrinter
{
   public StringEnum<PrinterType> PrintType = PrinterType.CommonPrinter;
}

        var list = PrinterType.GetValues().ToList();
        var e = new MyPrinter();
        var q = e.PrintType;
        if (e.PrintType == PrinterType.Ярлыков)
           ...
        if (e.PrintType.Contains("jh"))

or even like backing Field: 甚至喜欢支持Field:

        private StringEnum<PrinterType> _type;
        public string Type {... return _type... }

I would change it this way: 我会这样改变:

public class StringEnum<TChildType> where TChildType : StringEnum<TChildType>, new()
{
    private static readonly HashSet<string> members;
    private static readonly List<string> sortedmembers;

    private string _value;

    public string Value
    {
        get { return _value; }

        protected set
        {
            if (!Contains(value))
            {
                throw new ArgumentException(String.Format("Value '{0}' wasnt found in Enum", value));
            }
            _value = value;
        }
    }

    public static IEnumerable<string> Values
    {
        get { return sortedmembers; }
    }

    public static bool Contains(string value)
    {
        return members.Contains(value);
    }

    static StringEnum()
    {
        sortedmembers = Service.GetGenericConstProperties<string>(typeof(TChildType)); // .ToList() if necessary
        members = new HashSet<string>(sortedmembers);

        if (members.Count < 2) throw new Exception("Fill Enum!");
    }

    public static implicit operator StringEnum<TChildType>(string str)
    {
        return new TChildType { Value = str };
    }

    public static implicit operator string(StringEnum<TChildType> source)
    {
        return source != null ? source.Value : null;
    }

    public static StringEnum<TChildType> Parse(string value)
    {
        return (StringEnum<TChildType>)value;
    }

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

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

    public override bool Equals(object obj)
    {
        StringEnum<TChildType> value = obj as StringEnum<TChildType>;

        if (object.ReferenceEquals(value, null))
        {
            return false;
        }

        return StringComparer.Ordinal.Equals(Value, value.Value);
    }
}

An enum , like all value types, is immutable. 像所有值类型一样, enum是不可变的。 You can't change it. 您无法更改。 You can only reassign it. 您只能重新分配它。 I'm doing the same here. 我在这里也一样。 The Value.set is protected, and can be used only internally/by the subclasser of StringEnum<> . Value.set受保护,并且只能在内部/由StringEnum<>的子类使用。

I've implemented the GetHashCode / Equals / ToString . 我已经实现了GetHashCode / Equals / ToString

I've moved all the internal collections to static members, because they are common for all the StringEnum of the same TChildType 我已将所有内部集合移至static成员,因为它们对于同一TChildType所有StringEnumTChildType

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM