如何创建具有多个 属性 的 C# 枚举

How to create a c# enumeration with more than one property

我想创建一个类似对象的枚举,但有一个额外的 "property"。

例如我可以枚举星期几:

enum Day {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

现在,假设我还有一个 属性 我想每天存储。永远不会改变的东西。为了争论起见,假设我们有一个永远不变的工资率,周六为 1.5,周日为 2,其他时间为 1。

枚举无法做到这一点。我正在考虑创建一个 "helper" 静态 class,它只会 return 这一秒 属性,但这看起来很笨拙。

static class Rate
{
    static float GetRate(Day d)
    {
        switch (d)
        {
            case Day.Saturday:
                return 1.5f;
            case Day.Sunday:
                return 2f;
            default:
                return 1f;

        }
    }
}

我可以使用 ReadOnlyCollection 来代替带助手的枚举 class,但这对于我需要的东西来说似乎很复杂且重量级。

去这里最好的方法是什么?

可能是这样的:

public struct Day
{
    public Day(int key, float rate)
    {
        _key = key;
        _rate = rate;
    }
    private readonly int _key;
    private readonly float _rate;
    public int Key => _key;
    public float Rate => _rate;

    public static readonly Day
        Monday = new Day(0, 1f),
        Tuesday = new Day(0, 1f), ...;

    public static implicit operator int(Day day) => day.Key;
}

然后 Day.Monday.Rate 起作用,int day = Day.Monday 起作用。

您可以像这样向枚举值添加自定义属性:

enum Day {
    [MyAttr(Rate=1.5f)]
    Sunday, 
    [MyAttr(Rate=2)]
    Monday
}

public class MyAttr : Attribute {
    public float Rate {get;set;}
}

然后像这样读取属性:

public float GetRate(Day day) {
    MemberInfo memberInfo = typeof(Day).GetMember(day.ToString()).FirstOrDefault();

    if (memberInfo != null) {
        MyAttr attribute = (MyAttr)memberInfo
            .GetCustomAttributes(typeof(MyAttr), false)
            .FirstOrDefault();
        return attribute.Rate;
    }

    return 0;
}

C# 枚举值是简单的单一值,这与其他语言不同,在其他语言中它们可以是复杂类型(例如元组)。

如果枚举值表示不可变数据的 "key",您可以通过使用带有 switch 块的扩展方法来破解它 - 类似于您的示例,但使用时语法更清晰:

enum Day {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

public static class DayExtensions
{
    public static Single GetRate(this Day d)
    {
        switch( d )
        {
            case Day.Saturday:
                return 1.5f;
            case Day.Sunday:
                return 2f;
            default:
                return 1f;
        }
    }
}

用法:

Day d = Day.Monday;
Single rate = d.GetRate();

您可以使用带有预定义静态实例的密封 class。额外的 属性(或属性)可以读作 属性,或通过隐式转换。

public sealed class Day
{
    private Day(float rate)
    {
        m_Rate = rate;
    }

    private readonly float m_Rate;
    public float Rate { get { return m_Rate; } }

    public static readonly Day Saturday = new Day(1.5f);
    public static readonly Day Sunday = new Day(2f);
    public static readonly Day Monday = new Day(1f);
    public static readonly Day Tuesday = new Day(1f);
    public static readonly Day Wednesday = new Day(1f);
    public static readonly Day Thursday = new Day(1f);
    public static readonly Day Friday = new Day(1f);

    public static implicit operator float(Day day)
    {
        return day.m_Rate;
    }
}

用法:

var day = Day.Sunday;
var rate = day.Rate;      // Use property
float rate2 = day;        // Use implicit conversion