简体   繁体   English

在 C# 中表示参数化枚举的最佳方式?

[英]Best way to represent a parameterized enum in C#?

Are there any good solutions to represent a parameterized enum in C# 3.0 ?是否有任何好的解决方案来表示C# 3.0中的参数化枚举? I am looking for something like OCaml or Haxe has.我正在寻找像OCamlHaxe这样的东西。 I can only think of class hierarchy with a simple enum field for easy switching for now, maybe there are better ideas?我现在只能想到 class 层次结构,带有一个简单的枚举字段以便于切换,也许有更好的想法?

See Ocaml example below in one of the replies, a Haxe code follows:请参阅下面其中一个回复中的 Ocaml 示例,以下是 Haxe 代码:

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

Not being familiar with OCaml or Haxe, and not being clever enough to understand the other explanations, I went and looked up the Haxe enum documentation - the 'Enum Type Parameters' bit at the bottom seems to be the relevant part.不熟悉 OCaml 或 Haxe,也不够聪明,无法理解其他解释,我去查阅了Haxe 枚举文档——底部的“枚举类型参数”位似乎是相关部分。

My understanding based on that is as follows:基于此,我的理解如下:

A 'normal' enum is basically a value which is restricted to the things that you have defined in your enum definition. “正常”枚举基本上是一个值,仅限于您在枚举定义中定义的内容。 C# Example: C# 示例:

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

c can either be Red , Green , Yellow , or Blue , but nothing else. c可以是RedGreenYellowBlue ,但没有别的。

In Haxe, you can add complex types to enums, Contrived example from their page:在 Haxe 中,您可以将复杂类型添加到枚举,从他们的页面中设计的示例:

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

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

What this appears to mean is that c is restricted to either being the literal value empty (like our old fashioned C# enums), or it can also be a complex type cons(item, next) , where item is a T and next is a Cell<T> .似乎意味着c被限制为empty字面值(如我们老式的 C# 枚举),或者它也可以是复杂类型cons(item, next) ,其中itemTnextCell<T>

Not having ever used this it looks like it is probably generating some anonymous types (like how the C# compiler does when you do new { Name='Joe'} .从未使用过它,它看起来可能会生成一些匿名类型(例如 C# 编译器在执行new { Name='Joe'}时所做的事情。
Whenever you 'access' the enum value, you have to declare item and next when you do so, and it looks like they get bound to temporary local variables.每当您“访问”枚举值时,都必须声明itemnext ,并且看起来它们被绑定到临时局部变量。

Haxe example - You can see 'next' being used as a temporary local variable to pull data out of the anonymous cons structure: Haxe 示例 - 您可以看到 'next' 被用作临时局部变量以从匿名 cons 结构中提取数据:

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

To be honest, this blew my mind when I 'clicked' onto what it seemed to be doing.老实说,当我“点击”它似乎在做什么时,这让我大吃一惊。 It seems incredibly powerful, and I can see why you'd be looking for a similar feature in C#.它看起来非常强大,我明白您为什么要在 C# 中寻找类似的功能。

C# enums are pretty much the same as C/++ enums from which they were originally copied. C# 枚举与最初复制它们的 C/++ 枚举几乎相同。 It's basically a nice way of saying #define Red 1 so the compiler can do comparisons and storage with integers instead of strings when you are passing Color objects around.这基本上是#define Red 1的一种很好的说法,因此当您传递Color对象时,编译器可以使用整数而不是字符串进行比较和存储。

My stab at doing this in C# would be to use generics and interfaces.我在 C# 中这样做的尝试是使用 generics 和接口。 Something like this:像这样的东西:

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 */; }
}

Then you could have a List<ICell<T>> which would contain items and next cell, and you could insert EmptyCell at the end (or just have the Next reference explicitly set to null).然后你可以有一个List<ICell<T>>包含项目和下一个单元格,你可以在末尾插入EmptyCell (或者只是将Next引用显式设置为 null)。 The advantages would be that because EmptyCell contains no member variables, it wouldn't require any storage space (like the empty in Haxe), whereas a Cons cell would.优点是因为EmptyCell不包含成员变量,它不需要任何存储空间(如 Haxe 中的empty ),而Cons单元格则需要。
The compiler may also inline / optimize out the methods in EmptyCell as they do nothing, so there may be a speed increase over just having a Cons with it's member data set to null.编译器还可以内联/优化EmptyCell中的方法,因为它们什么都不做,因此与仅将其成员数据集为 null 的Cons相比,速度可能会有所提高。

I don't really know.我真的不知道。 I'd welcome any other possible solutions as I'm not particularly proud of my one:-)我欢迎任何其他可能的解决方案,因为我对我的解决方案并不特别自豪:-)

Use a class that with static properties to represent the enumeration values.使用具有static属性的 class 来表示枚举值。 You can, optionally, use a private constructor to force all references to the class to go through a static property.您可以选择使用私有构造函数通过 static 属性将所有对 class 的引用强制为 go。

Take a look at the System.Drawing.Color class.看看System.Drawing.Color class。 It uses this approach.它使用这种方法。

C# (the .NET framework in general, as far as I know) doesn't support parametrized enums like Java does. C#(据我所知,一般是 .NET 框架)不支持像 Java 那样的参数化枚举。 That being said, you might want to look at Attributes.话虽如此,您可能想查看属性。 Some of the features that Java enums are capable of are somewhat doable through Attributes. Java 枚举能够实现的一些功能在某种程度上可以通过属性实现。

What's wrong with just using a class for this?仅使用 class 有什么问题? Its ugly, but thats how the Java people did it until they had language integrated Enum support!它很难看,但 Java 的人就是这样做的,直到他们拥有语言集成的 Enum 支持!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM