我正在实现代表距离(或长度)的值类型。 有一个枚举代表不同的度量单位,例如:
public enum DistanceUnit
{
Millimeter,
Centimeter,
Meter,
Kilometer,
Inch,
Foot,
Yard,
Mile
};
这些测量属于两个系统之一 - 公制或英制。由于枚举不支持层次结构,表示这种层次结构的最佳模式是什么?
是否使用位标志? 或者使用两个单独的枚举以及一些方法来关联它们? 或者声明静态成员而不是枚举?
给我一些建议...... 你将如何实现这个?
编辑 - 更多说明: 我有几个不可变的结构(由T4生成)代表各种测量:
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 ....
...等,以及手动编码的不可变距离,旨在表示任何度量:
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
}
}
在讨论是否应通过调用代码将距离转换为正确的UOM时,此处的目标是让ToString在当前UnitOfMeasure表示的相同度量(英制或公制)上向上或向下转换值
显然这可以全部硬编码到ToString方法中,但鉴于我也在为整个shibang实现TypeConverters和FormatProviders,我想找到一种通用方法,从DistanceUnit中找出什么,适当的下一个或下一个下降的计量单位将是。
我是不是想以这种方式实施错误的树?
答案 0 :(得分:10)
你真的需要enum
吗?也许,一个简单的value object会做什么?
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();
答案 1 :(得分:2)
一般来说,我会选择 Anton 的解决方案。但是如果你的实现不能使用它,并且你需要使用与枚举类似的东西, 我认为这是使用单位的自然方式:
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
具有相同的结构..
答案 2 :(得分:1)
也许您只需要一个返回相应单位子集的函数
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;
}
}
}