使用枚举实现层次结构的最佳 C# 模式是什么?
我正在实现代表距离(或长度)的值类型。 有一个枚举代表不同的测量单位,例如:
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 中找出合适的下一步-向上或向下的测量单位是。
我想以这种方式实施是不是找错了方向?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你真的需要一个
enum
吗?也许,一个简单的 值对象 就可以了?通过扩展方法,您和正确定义的运算符可以获得非常类似于 Ruby 的语法:
Do you really need an
enum
here? Maybe, a simple value object will do?With extension methods you and properly defined operators can get very Ruby-like syntax:
一般来说,我会选择安东的解决方案。但是如果你的实现不能使用它,并且你需要使用类似于枚举的东西,
我认为这是使用单位的自然方式:
为了像这样使用它,应该有:
其中
MetricDistanceUnit
是:并且
ImperialDistanceUnit
具有相同的结构..Generally speaking, I would go with Anton's solution. But if your implementation can't use that, and you need things to be used similar to an enum,
I think this is a natural way to use the units:
In order to use it like that, there should be:
Where
MetricDistanceUnit
is:And
ImperialDistanceUnit
has the same structure..也许您需要的只是一个返回相应单位子集的函数
Maybe all you need is a function that returns a corresponding unit subset