使用枚举实现层次结构的最佳C#模式是什么?

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

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

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

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

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


编辑 – 更多说明:我有几个不可变的结构(由T4生成)代表各种测量:

 public struct Meters : IEquatable, IEquatable, IEquatable, ... 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 .... 

…等,以及手动编码的不可变距离,旨在表示任何度量:

 public struct Distance : IEquatable, IEquatable, IEquatable, ... 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 } } 

在讨论是否应通过调用代码将距离转换为正确的UOM时,此处的目标是让ToString在由当前UnitOfMeasure表示的相同度量(英制或公制)上向上或向下转换值。

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

我是想通过这种方式实施错误的树吗?

你真的需要一个enum吗? 也许,一个简单的价值对象会做什么?

 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); } } 

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

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

一般来说,我会选择安东的解决方案。 但是如果你的实现不能使用它,并且你需要使用类似于枚举的东西,我认为这是使用单位的自然方式:

 DistanceUnit.Metric.Millimeter DistanceUnit.Imperial.Inch 

为了像这样使用它,应该有:

 public static class DistanceUnit { public static MetricDistanceUnit Metric; public static ImperialDistanceUnit Imperial; } 

MetricDistanceUnit是:

 public enum MetricDistanceUnit { Millimeter, Centimeter ... } 

ImperialDistanceUnit具有相同的结构..

也许您需要的只是一个返回相应单元子集的函数

 class UnitSystem { public enum Type { Metric, Imperial } public static DistanceUnit[] GetUnits(Type type) { switch (type) { case Type.Metric: return new DistanceUnit[] { DistanceUnit.Millimeter, DistanceUnit.Centimeter, DistanceUnit.Meter, DistanceUnit.Kilometer } case Type.Imperial: return new DistanceUnit[] { DistanceUnit.Inch, DistanceUnit.Foot, DistanceUnit.Yard, DistanceUnit.Mile } } } public static Type GetType(DistanceUnit unit) { switch (unit) { case DistanceUnit.Millimeter: case DistanceUnit.Centimeter: case DistanceUnit.Meter: case DistanceUnit.Kilometer: return Type.Metric; case DistanceUnit.Inch: case DistanceUnit.Foot: case DistanceUnit.Yard: case DistanceUnit.Mile: return Type.Imperial; } } }