代码之家  ›  专栏  ›  技术社区  ›  Mark

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

  •  9
  • Mark  · 技术社区  · 14 年前

    我正在实现表示距离(或长度)的值类型。

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

    这些测量分为两种系统之一-公制或英制。既然enum不支持层次结构,那么表示这个层次结构的最佳模式是什么?

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

    给我一些建议。。。你会怎么做


    编辑-更多说明: 我有几个不可变的结构(由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
        }
    }
    

    显然,这些都可以硬编码到ToString方法中,但是考虑到我也在为整个shibang实现typeconverter和FormatProviders,我想找到一种通用的方法,从一个DistanceUnit中找出合适的下一个向上或下一个向下的度量单位。

    3 回复  |  直到 14 年前
        1
  •  10
  •   Jens    14 年前

    你真的需要医生吗 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();
    
        2
  •  2
  •   Oren A    14 年前

    一般来说,我会和你一起去 安东 的解决方案。但是如果您的实现不能使用它,并且您需要使用类似于枚举的东西, 单位:

    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

        3
  •  1
  •   Dialecticus    14 年前

    也许你所需要的只是一个函数,返回一个对应的单位子集

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