【问题标题】:Best way to represent a parameterized enum in C#?在 C# 中表示参数化枚举的最佳方法?
【发布时间】:2008-09-15 20:50:38
【问题描述】:

C# 3.0 中表示参数化枚举有什么好的解决方案吗?我正在寻找类似OCamlHaxe 的东西。我现在只能想到带有简单枚举字段的类层次结构以便于切换,也许有更好的想法?

请参阅下面其中一个回复中的 Ocaml 示例,以下是 Haxe 代码:

enum Tree {
   Node(left: Tree, right: Tree);
   Leaf(val: Int);
}

【问题讨论】:

  • 对于我们这些不了解 OCaml 或 haXe 的人,您能提供和示例吗?

标签: c# enums ocaml haxe


【解决方案1】:

不熟悉 OCaml 或 Haxe,也不够聪明,无法理解其他解释,我去查找了 Haxe enum documentation - 底部的“枚举类型参数”位似乎是相关部分。

基于此,我的理解如下:

“正常”枚举基本上是一个值,仅限于您在枚举定义中定义的内容。 C# 示例:

enum Color{ Red, Green, Yellow, Blue };
Color c = Color.Red;

c 可以是 RedGreenYellowBlue,但不能是别的。

在 Haxe 中,您可以将复杂类型添加到枚举中,从他们的页面中创建示例:

enum Cell<T>{ 
  empty; 
  cons( item : T, next : Cell<T> )
}

Cell<int> c = <I don't know>;

这个出现的意思是c被限制为文字值empty(就像我们老式的C#枚举),或者它也可以是一个复杂类型@987654331 @,其中itemTnextCell&lt;T&gt;

从未使用过它,它看起来可能会生成一些匿名类型(就像 C# 编译器在您执行 new { Name='Joe'} 时所做的那样。
每当您“访问”枚举值时,都必须声明 itemnext,看起来它们绑定到临时局部变量。

Haxe 示例 - 您可以看到 'next' 被用作临时局部变量以从匿名 cons 结构中提取数据:

switch( c ) {
  case empty : 0;
  case cons(item,next): 1 + cell_length(next);
}

说实话,当我“点击”它似乎在做什么时,这让我大吃一惊。它看起来非常强大,我明白您为什么要在 C# 中寻找类似的功能。

C# 枚举与最初复制它们的 C/++ 枚举几乎相同。这基本上是表达#define Red 1 的好方法,因此当您传递Color 对象时,编译器可以使用整数而不是字符串进行比较和存储。

我在 C# 中这样做的目的是使用泛型和接口。像这样的:

public interface ICell<T> {
   T Item{ get; set; }
   ICell<T>{ get; set; }
}

class Cons<T> : ICell<T> {
  public T Item{ get; set; } /* C#3 auto-backed property */
  public Cell<T> Next{ get; set; }
}

class EmptyCell<T> : ICell<T>{
  public T Item{ get{ return default(T); set{ /* do nothing */ }; }
  public ICell<T> Next{ get{ return null }; set{ /* do nothing */; }
}

然后你可以有一个List&lt;ICell&lt;T&gt;&gt;,它包含项目和下一个单元格,你可以在末尾插入EmptyCell(或者只是将Next引用明确设置为null)。 优点是因为EmptyCell 不包含成员变量,所以它不需要任何存储空间(如 Haxe 中的 empty),而 Cons 单元格则需要。
编译器还可以内联/优化 EmptyCell 中的方法,因为它们什么都不做,因此与将成员数据设置为 null 的 Cons 相比,速度可能会有所提高。

我真的不知道。我欢迎任何其他可能的解决方案,因为我对我的解决方案并不特别自豪:-)

【讨论】:

  • 谢谢,这就是我真正的想法,但您提供了非常详细的解释如何做到这一点!是的,可能没有比这更好的了……
【解决方案2】:

使用具有静态属性的来表示枚举值。您可以选择使用私有构造函数来强制对类的所有引用通过静态属性。

看看System.Drawing.Color 类。它使用这种方法。

【讨论】:

    【解决方案3】:

    C#(据我所知,一般是 .NET 框架)不像 Java 那样支持参数化枚举。话虽如此,您可能想查看属性。 Java 枚举能够实现的一些功能在某种程度上可以通过 Attributes 实现。

    【讨论】:

    • 如果我错了,请纠正我,但我认为 Java 枚举允许参数 - 但对于所有枚举构造都相同,而不是像 OCaml 那样每个构造的唯一参数列表。我需要 ocaml 方式,所以属性在这里没有多大帮助 - 但无论如何谢谢!
    【解决方案4】:

    仅仅为此使用一个类有什么问题?它很丑陋,但 Java 人就是这样做的,直到他们有语言集成的 Enum 支持!

    【讨论】:

    • 类的问题是很难切换。给定一个枚举值,我想要一种快速简单的方法来理解它是什么以及它的论点是什么。我可以通过类层次结构和简单的枚举开关来做到这一点,但这听起来不太优雅..
    猜你喜欢
    • 1970-01-01
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多