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

发布于 2024-07-04 13:51:51 字数 358 浏览 10 评论 0 原文

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

请参阅以下回复之一中的 Ocaml 示例,Haxe 代码如下:

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

Are there any good solutions to represent a parameterized enum in C# 3.0? I am looking for something like OCaml or Haxe has. I can only think of class hierarchy with a simple enum field for easy switching for now, maybe there are better ideas?

See Ocaml example below in one of the replies, a Haxe code follows:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

月下凄凉 2024-07-11 13:51:52

仅使用类来实现此目的有什么问题吗? 它很难看,但这就是 Java 人所做的,直到他们有了语言集成的 Enum 支持!

What's wrong with just using a class for this? Its ugly, but thats how the Java people did it until they had language integrated Enum support!

秋叶绚丽 2024-07-11 13:51:52

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

C# (the .NET framework in general, as far as I know) doesn't support parametrized enums like Java does. 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.

层林尽染 2024-07-11 13:51:51

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

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

Use a class that with static properties to represent the enumeration values. You can, optionally, use a private constructor to force all references to the class to go through a static property.

Take a look at the System.Drawing.Color class. It uses this approach.

攀登最高峰 2024-07-11 13:51:51

由于不熟悉 OCaml 或 Haxe,也没有足够聪明来理解其他解释,我去查找了 Haxe 枚举文档 - 底部的“枚举类型参数”位似乎是相关部分。

我的理解如下:

“正常”枚举基本上是一个仅限于您在枚举定义中定义的内容的值。 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 仅限于文字值 (就像我们老式的 C# 枚举),或者它也可以是复杂类型 cons(item, next),其中 item 是一个 TnextCell

从未使用过它,看起来它可能会生成一些匿名类型(就像 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> ,其中包含项目和下一个单元格,并且你可以在末尾插入 EmptyCell (或者只是将 Next 引用显式设置为 null)。
优点是,由于 EmptyCell 不包含任何成员变量,因此不需要任何存储空间(如 Haxe 中的 empty),而 缺点 单元格会。
编译器还可能内联/优化 EmptyCell 中的方法,因为它们不执行任何操作,因此与仅将 Cons 的成员数据设置为 null 相比,速度可能会有所提高。

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

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.

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:

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

c can either be Red, Green, Yellow, or Blue, but nothing else.

In Haxe, you can add complex types to enums, Contrived example from their page:

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>.

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'}.
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.

Haxe example - You can see 'next' being used as a temporary local variable to pull data out of the anonymous cons structure:

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# enums are pretty much the same as C/++ enums from which they were originally copied. 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.

My stab at doing this in C# would be to use generics and interfaces. 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).
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.
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.

I don't really know. I'd welcome any other possible solutions as I'm not particularly proud of my one :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文