What's the best C# pattern for implementing a hierarchy with an enum?

笑着哭i 提交于 2019-12-03 12:37:26
Anton Gogolev

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

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:

DistanceUnit.Metric.Millimeter  
DistanceUnit.Imperial.Inch  

In order to use it like that, there should be:

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

Where MetricDistanceUnit is:

public enum MetricDistanceUnit  
{
   Millimeter, Centimeter ...
}

And ImperialDistanceUnit has the same structure..

Maybe all you need is a function that returns a corresponding unit subset

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;
    }
  }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!