用枚举实现层次结构的最佳C#模式是什么? [英] What's the best C# pattern for implementing a hierarchy with an enum?

查看:91
本文介绍了用枚举实现层次结构的最佳C#模式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现代表距离(或长度)的值类型。
有一个枚举代表不同的度量单位,例如:

  public enum DistanceUnit 
{
毫米,
厘米,
米,
公里,
英寸,
脚,
院子,
Mile
};

这些测量属于两个系统之一,无论是公制还是英制。由于枚举不支持hierachies,代表这个层次结构的最佳模式是什么?



是使用位标志吗?
或者使用两个单独的枚举和一些方法来关联它们?
或者声明静态成员而不是枚举?



给我一​​些建议...你会如何实现这个?




编辑 - 更多澄清:
我有几个不可变的结构(由T4生成),代表各种测量: p>

  public struct Meters:IEquatable< Distance> 
IEquatable& Meters>,
IEquatable< Millimeters> .. IComparable<>等等..
{
public readonly decimal值;
...
public static implicit operator Distance(Meters other){
//可隐式转换为Distance
}
}

public struct Millimeters ...
public struct Centimeters ....

...等,以及用于代表任何度量的手工编码的不可变距离:

  public struct距离:IEquatable< Distance> 
IEquatable& Meters>,
IEquatable< Millimeters> ...
IFormattable
{

public readonly decimal值;
public readonly DistanceUnits UnitOfMeasure;
...
public string ToString(string format,IFormatProvider provider)
{
//逻辑:
//如果UOM = Meters and Value< .1然后显示为10厘米而不是.1 M
//如果UOM =英寸,值的倍数为12,显示为脚
//等,etc
}
}

前面讨论通过调用代码是否将距离转换为正确的UOM ,这里的目标是让ToString在当前UnitOfMeasure所代表的相同测量(英制或公制)上向上或向下转换值。



显然这可以全部要硬编码到ToString方法中,但是鉴于我也为整个shibang实现了TypeConverters和FormatProviders,我想找到一个通用的方法来从DistanceUnit中找出适当的下一个或下一个下调单位将是。



我是否以这种方式执行错误的树?

解决方案

你真的需要一个枚举吗?也许一个简单的值对象将会执行?



public class Distance
{
private readonly decimal mm;

  

公开十进制数
{
获取{返回毫米* 0.001米;
}

私人距离(十进制毫米)
{
this.millimeters = millisec;
}

public static Distance Yards(decimal yards)
{
return new Distance(yards * 914.4m);
}
}

使用扩展方法,您和正确定义的运算符可以获得类似Ruby的语法:

  var theWholeNineYards = 9.Yards()+ 34.Inches(); 


I'm implementing value types which represents a distance (or length). There's an enum that represents the different units of measure, eg:

public enum DistanceUnit 
{
   Millimeter,
   Centimeter,
   Meter,
   Kilometer,
   Inch,
   Foot,
   Yard,
   Mile
};

These measurements fall into one of two systems - either metric or imperial. Since enum doesn't support hierachies, what's the best pattern for representing this hierarchy?

Is it to use bit flags? Or use two seperate enums along with some methods to correlate them? Or to declare static members instead of enums?

Give me some advice... how would you implement this?


Edit - More clarification: I have several immutable structs (generated by T4) which represent various measurements:

public struct Meters : IEquatable<Distance>, 
                       IEquatable<Meters>, 
                       IEquatable<Millimeters>, ... IComparable<> etc.. etc..
{
    public readonly decimal Value;
    ...
    public static implicit operator Distance (Meters other) {
        // Can implicitly cast to Distance
    }
}

public struct Millimeters ...
public struct Centimeters ....

... etc, as well as a hand-coded immutable Distance, intended to represent any measure:

public struct Distance : IEquatable<Distance>, 
                       IEquatable<Meters>, 
                       IEquatable<Millimeters>, ...
                       IFormattable
{

    public readonly decimal Value;
    public readonly DistanceUnits UnitOfMeasure;
    ...
    public string ToString(string format, IFormatProvider provider)
    {
        // Logic:
        // If UOM = Meters and Value < .1 then display as "10 cm" instead of ".1 M"
        // If UOM = Inches and value multiple of 12, display as feet
        // etc, etc
    }
}

Foregoing a discussion about whether the Distance should be converted to the correct UOM by calling code, the goal here is for ToString to convert the value up or down on the same measurement (imperial or metric) that is represented by the current UnitOfMeasure.

Obviously this could all be hard coded into the ToString method, but given that I'm also implementing TypeConverters and FormatProviders for this whole shibang, I'd like to find a generic means of figuring out, from a DistanceUnit, what the appropriate next-up or next-down unit of measure would be.

Am I barking up the wrong tree by wanting to implement in this manner?

解决方案

Do you really need an enum here? Maybe, a simple value object will do?

public class Distance
{
    private readonly decimal millimeters;

    public decimal Meters
    { 
        get { return millimeters * 0.001m; } 
    }

    private Distance(decimal millimeters)
    {
        this.millimeters = millimeters;
    }

    public static Distance Yards(decimal yards)
    {
        return new Distance(yards * 914.4m);
    }
}

With extension methods you and properly defined operators can get very Ruby-like syntax:

var theWholeNineYards = 9.Yards() + 34.Inches();

这篇关于用枚举实现层次结构的最佳C#模式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆