是否有任何好的解决方案来表示C# 3.0中的参数化枚举? 我正在寻找类似OCaml或Haxe的东西。 我现在只能考虑使用简单的枚举字段进行轻松切换的类层次结构,也许有更好的主意?
请参阅以下答复之一中的Ocaml示例,遵循Haxe代码:
1 2 3 4
| enum Tree {
Node(left: Tree, right: Tree);
Leaf(val: Int);
} |
我不熟悉OCaml或Haxe,也不够聪明,无法理解其他解释,所以我去查阅了Haxe枚举文档-底部的" Enum Type Parameters"位似乎是相关的部分。
基于此,我的理解如下:
"正常"枚举基本上是一个值,该值仅限于您在枚举定义中定义的内容。 C#示例:
1 2
| enum Color{ Red, Green, Yellow, Blue };
Color c = Color.Red; |
c可以是Red,Green,Yellow或Blue,但是没有其他内容。
在Haxe中,您可以从枚举的页面中向枚举添加复杂类型(人为的示例):
1 2 3 4 5 6
| enum Cell< T >{
empty;
cons( item : T, next : Cell< T > )
}
Cell<int> c = <I don't know>; |
这似乎意味着c被限制为文字值empty(就像我们的老式C#枚举一样),或者也可以是复杂类型cons(item, next),其中item是,并且next是Cell< T >。
从未使用过它,看起来好像正在生成一些匿名类型(例如,执行new { Name='Joe'}时C#编译器的工作方式)。
每当"访问"枚举值时,都必须在声明时声明item和next,看起来它们已绑定到临时局部变量。
Haxe示例-您可以看到'next'被用作临时局部变量,以将数据从匿名cons结构中拉出:
1 2 3 4
| switch( c ) {
case empty : 0;
case cons(item,next): 1 + cell_length(next);
} |
老实说,当我"点击"它似乎正在做的事情时,这让我大吃一惊。它似乎非常强大,我可以理解为什么您会在C#中寻找类似的功能。
C#枚举与最初复制它们的C / ++枚举几乎相同。这基本上是说#define Red 1的一种好方法,因此,当您传递Color对象时,编译器可以使用整数而不是字符串进行比较和存储。
我在C#中这样做的目的是使用泛型和接口。像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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>,其中将包含项目和下一个单元格,并且可以在末尾插入EmptyCell(或者只是将next引用显式设置为null)。
优点是,因为EmptyCell不包含成员变量,所以它不需要任何存储空间(例如Haxe中的empty),而Cons单元则不需要。
编译器还可以内联/优化EmptyCell中的方法,因为它们什么也不做,因此与仅将Cons的成员数据设置为null的方法相比,可能会提高速度。
我真的不知道我欢迎任何其他可能的解决方案,因为我对自己的解决方案并不感到特别骄傲:-)
使用具有静态属性的类来表示枚举值。您可以选择使用私有构造函数来强制对类的所有引用都经过静态属性。
看一下System.Drawing.Color类。它使用这种方法。
仅为此使用类有什么问题?这很丑陋,但这就是Java人员在集成了Enum语言支持之前是如何做到的!
C#(据我所知,通常是.NET框架)不像Java那样支持参数化枚举。话虽这么说,您可能想看看属性。 Java枚举所具有的某些功能可以通过属性来实现。