簡體   English   中英

使用枚舉實現層次結構的最佳C#模式是什么?

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

我正在實現代表距離(或長度)的值類型。 有一個枚舉代表不同的度量單位,例如:

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

這些測量屬於兩個系統中的一個 - 公制或英制。 由於枚舉不支持hierachies,表示這種層次結構的最佳模式是什么?

它是否使用位標志? 或者使用兩個單獨的枚舉以及一些方法來關聯它們? 或者聲明靜態成員而不是枚舉?

給我一些建議...... 將如何實現這一點?


編輯 - 更多說明:我有幾個不可變的結構(由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中找出適當的下一個 - 上行或下行單位將是。

我是不是想以這種方式實施錯誤的樹?

你真的需要一個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;
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM