何时以及如何使用枚举类而不是枚举?

Chr*_*ams 9 c# design-patterns enumeration separation-of-concerns

最近工作的开发人员开始在枚举通常适合的地方使用类模式而不是枚举.相反,他使用类似于下面的东西:

internal class Suit
{
    public static readonly Suit Hearts = new Suit();
    public static readonly Suit Diamonds = new Suit();
    public static readonly Suit Spades = new Suit();
    public static readonly Suit Clubs = new Suit();
    public static readonly Suit Joker = new Suit();
    private static Suit()
    {

    }
    public static bool IsMatch(Suit lhs, Suit rhs)
    {
        return lhs.Equals(rhs) || (lhs.Equals(Joker) || rhs.Equals(Joker));
    }
}
Run Code Online (Sandbox Code Playgroud)

他的推理是它无形地看起来像枚举,但允许他包含与枚举有关的方法(如上面的IsMatch),它包含在枚举本身中.

他称这是一个Enumeration课程,但这不是我以前见过的.我想知道优点和缺点是什么以及我可以在哪里找到更多信息?

谢谢

编辑:他描述的另一个优点是能够为枚举添加特定的ToString()实现.

小智 6

枚举在很多情况下都很好,但在其他情况下却很差。通常我会发现 Enums 的一些问题:

  • 与枚举相关的行为分散在应用程序中
  • 新的枚举值需要霰弹枪手术
  • 枚举不遵​​循开闭原则

由于枚举行为分散,我们永远无法将其带回源类型,因为枚举类型不能具有任何行为(或状态)。

另一方面,使用枚举类

每个枚举类型的所有变体不仅可以向下推送到枚举类,还可以向下推送到每个特定的子类型。

枚举在各种场景中都能很好地工作,但在您的域模型中可能会很快分解。枚举类提供了许多相同的可用性,并具有成为行为目的地的额外好处。

不再需要 switch 语句,因为我可以将可变性和知识推回模型内部。如果由于某种原因我需要检查特定的枚举类值,该选项仍然对我开放。这种模式不应该取代所有的枚举,但有一个替代方案是很好的。

可以在这里阅读


Eli*_*nti 4

枚举的主要优点是它们基本上是带有一些命名值的整数,因此它们本质上是可移植和可序列化的。枚举上的算术和逻辑运算也更快。

当您需要具有额外状态信息的不透明值时,可以使用枚举类。例如,通用数据访问层可以具有如下接口:

公共静态类 Dal
{
    public static Record Query(Operation操作,Parameters参数);
}

var 结果 = Dal.Query(Operation.DoSomething, new DoSomethingParameters {...});

对于 Dal 的用户来说,操作只是可用操作的枚举,但它可以包含连接字符串、SQL 语句或存储过程以及通用 Dal 所需的任何其他数据。

另一个“常见”用途是系统(状态或策略)中的公共模式。从用户的角度来看,模式是一个不透明的值,但它可能包含对系统实现至关重要的信息或内部功能。一个人为的例子:

公共课系统
{
   公共SystemMode模式;
   公共无效保存()
   {
      模式.保存();
   }
   公共系统文档读取()
   {
      返回模式.Read();
   }
}

公共抽象类 SystemMode
{
   公共静态 SystemMode ReadOnly = new ReadOnlyMode();
   公共静态 SystemMode ReadWrite = new ReadWriteMode();

   内部抽象 void Save();
   内部抽象SystemDocument Read();

   私有类 ReadOnlyMode :系统模式
   {
      内部重写 void Save() {...}
      内部重写 SystemDocument Read() {...}
   }

   私有类 ReadWriteMode :系统模式
   {
      内部重写 void Save() {...}
      内部重写 SystemDocument Read() {...}
   }
}


TheSystem.Mode = SystemMode.ReadOnly;

我认为仅仅拥有 IsMatch 静态方法并不能保证不使用简单的枚举。在这种情况下,可以使用扩展方法来实现非常相似的效果。