typesafe枚举和隐式运算符

时间:2016-05-19 16:52:44

标签: c#

我创建了一个实现Unit枚举模式的typesafe类。我在其中实现了implicit operator以简化其使用。但我想重构从stringUnit的隐式运算符。目前,我正在使用switch块,但是一旦添加更多单元,这将非常快。我目前的代码看起来像这样。

[DataContract]
public class Unit
{
    public static readonly Unit USFeet = new Unit("US Feet", 1);
    public static readonly Unit Meters = new Unit("Meters", 0.3048006096);
    [DataMember] public double ConversionConstant { get; private set; }
    [DataMember] private string Name { get; set; }

    private Unit(string name, double conversionConstant)
    {
        Name = name;
        ConversionConstant = conversionConstant;
    }
    public override string ToString()
    {
        return Name;
    }

    public static implicit operator string(Unit unit)
    {
        return unit.Name;
    }

    public static implicit operator Unit(string name)
    {
        switch (name)
        {
            case "US Feet":
                return USFeet;
            case "Meters":
                return Meters;
            default:
                return null;
        }
    }
}

所以我的问题是,有没有更好的方法来解决这个问题而不是使用switch阻止?

我尝试过类似的东西,但它不起作用......

    public static SortedList<string, Unit> UnitList = new SortedList<string, Unit>();
    private Unit(string name, double conversionConstant)
    {
        Name = name;
        ConversionConstant = conversionConstant;
        UnitList.Add(name, this);
    }
    public static implicit operator Unit(string name)
    {
        return UnitList[name];
    }

2 个答案:

答案 0 :(得分:1)

您可以构建查找表,并从.ctor

更新它
private static Dictionary<string, Unit> definedUnits = new Dictionary<string, UserQuery.Unit>();

private Unit(string name, double conversionConstant)
{
    Name = name;
    ConversionConstant = conversionConstant;

    definedUnits.Add(name, this);
}

public static implicit operator Unit(string name)
{
    Unit result;

    return definedUnits.TryGetValue(name, out result) ? result : null;
}

您还可以使用反射动态构建该表:

private static Dictionary<string, Unit> definedUnits = typeof(Unit)
    .GetFields(BindingFlags.Public | BindingFlags.Static)
    .Where(x => x.IsInitOnly && x.FieldType == typeof(Unit))
    .ToDictionary(x => x.Name, x => (Unit)x.GetValue(null));

答案 1 :(得分:0)

看起来我上面尝试的东西在这样做时会起作用(我相信它叫做延迟初始化)

[DataContract]
public class Unit
{

    public static readonly Unit USFeet = new Unit("US Feet", 1);
    public static readonly Unit Meters = new Unit("Meters", 0.3048006096);

    private static Dictionary<string, Unit> _unitList;
    public static readonly Dictionary<string, Unit> UnitList = _unitList ?? (_unitList = new Dictionary<string, Unit>());

    [DataMember] private readonly double _conversionConstant;
    [DataMember] private readonly string _name;

    private Unit(string name, double conversionConstant)
    {
        _name = name;
        _conversionConstant = conversionConstant;
        UnitList.Add(name, this);
    }
}