为啥我们不能有“char”枚举类型

Posted

技术标签:

【中文标题】为啥我们不能有“char”枚举类型【英文标题】:Why we can't have "char" enum types为什么我们不能有“char”枚举类型 【发布时间】:2010-10-09 01:08:39 【问题描述】:

我想知道为什么我们不能将“char”作为底层枚举类型。 因为我们有 byte,sbyte,int,uint,long,ulong,short,ushort 作为底层 枚举类型。 其次,枚举的默认基础类型是什么?

【问题讨论】:

【参考方案1】:

我知道这是一个较老的问题,但这些信息会对我有所帮助:

在 C# .NET 4.0(甚至可能是 3.5,但我还没有测试过)中,使用 char 作为枚举的值类型似乎没有问题。这是我所做的,它完全有效:

public enum PayCode 
    NotPaid = 'N',
    Paid = 'P'

将枚举转换为字符:

PayCode enumPC = PayCode.NotPaid;
char charPC = (char)enumPC; // charPC == 'N'

将字符转换为枚举:

char charPC = 'P';
if (Enum.IsDefined(typeof(PayCode), (int)charPC))  // check if charPC is a valid value
    PayCode enumPC = (PayCode)charPC; // enumPC == PayCode.Paid

就像你对 char 类型所期望的那样,就像一个魅力一样!

【讨论】:

支持您的答案,但请注意答案中的枚举仍然有 int 作为基础类型。编译器将其视为int。希望 C# 没有这种边缘情况。 2019 年评论 - 如果您依赖底层的 .ToString() 调用,它实际上采用“NotPaid”和“Paid”,您可能会遇到自动截断或仅采用第一个字符的情况的名称 - 巧合的是,它与您看到的 Char 相同 "Paid" = 'P' "NotPaid" = 'N' MyEnum = 'Z' 将返回 'M' 例如【参考方案2】:

默认类型是 int。更多信息请参见 MSDN 上的 C#reference。您还可以在 MSDN 上找到指向 C# language specification 的链接。我认为限制的原因可能来自语言规范第 4.1.5 节中的这些陈述。

char 类型被归类为 整数类型,但它不同于 其他整数类型有两种方式:

• 没有隐式转换 从其他类型到 char 类型。在 特别是,即使 sbyte, byte 和 ushort 类型的范围为 完全可表示的值 使用 char 类型,隐式 从 sbyte、byte 或 ushort 到 char 不存在。

• char 类型的常量必须是 写成字符文字或 整数文字与 a 组合 强制转换为 char 类型。例如, (char)10 与 '\x000A' 相同。

【讨论】:

【参考方案3】:

这是我正在使用的解决方法

enum MyEnum

    AA = 'A',
    BB = 'B',
    CC = 'C'
;

static void Main(string[] args)

    MyEnum e = MyEnum.AA;
    char value = (char)e.GetHashCode(); //value = 'A'

【讨论】:

或者你可以只写(char) e而不写GetHashCode() 您只需要(char)e。 You're incurring boxing penalty by going for enum.GetHashCode.【参考方案4】:

从技术上讲,您不能这样做。但是,您可以将枚举转换为字节,然后将其转换为字符。如果您的目标是拥有这样的东西(意识到这是不可能的:

public enum CharEnum

    one = '1'

但是,您可以通过使用 ASCII 字节值然后进行转换来做到这一点:

public enum CharEnum

    one = 49,
    two = 50

然后您可以转换为 byte 和 char 以获取 char 值。它不是很漂亮,但它会起作用,如果得到一个字符是你的最终目标。如果您需要 ASCII 范围之外的字符,也可以使用 unicode 和 int 值。 :-)

【讨论】:

【参考方案5】:

请参阅Ecma International 中的 ECMA 标准 335,公共语言基础架构 (CLI)。 CLI 允许底层类型为 char 或 bool,但 C# 和 VB.Net 不允许。不管怎样,C++/CLI 确实允许 System::Char 作为底层类型。

我认为 C# 和 VB.Net 仅出于语法原因不允许 char 和 bool 作为基础类型。

【讨论】:

C++ char 与 C# char 不同,它与 C# sbyte 相同(这是允许的枚举基类型) @BenVoigt 你是正确的,即使它是在 C++/CLI 中定义的 System.Char 的底层类型在 C# 中也不起作用。如果 System.Char 都是 C++/CLI 的话,它确实可以作为底层类型工作,所以我会改变我的回答,因为它增加了理解。 @BenVoigt:C# 不能使用 IL 定义的 char 枚举,但 VB.NET 可以使用(与布尔枚举相同,但如果没有某种形式的自动否定,它们没有任何意义的错误条目,否则他们会阅读 if (!BoolEnum.Disabled) 以询问条目是否禁用。)。 @Christoph:与if (!false) 没有什么不同...实际上,该常量不会出现在条件控制表达式中,而是会出现var x = BoolEnum.Disabled; if (!x) ... ,这似乎是100% 正常的。 @BenVoigt:你是对的,如果有人像在var enabled = BoolEnum.Disabled; if (!enabled) ... 中那样正确使用它们,那么一切都很清楚,在var state = BoolEnum.Disabled; if (state == BoolEnum.Disabled) 中它也可以工作。我在 VB.NET 中尝试过一次,并认为 If Not BoolEnum.Disabled Then 询问它是否被禁用完全令人困惑,但你是对的,通常指的是变量而不是常量。让我们在 C# 和 VB.NET 中介绍它们,它们从 1.0 开始就已经在 CLI 中了!【参考方案6】:
char charPC = 'P';
if (Enum.IsDefined(typeof(PayCode), (PayCode)charPC))  
        // check if charPC is a valid value
        PayCode enumPC = (PayCode)charPC; // enumPC == PayCode.Paid

做了一个小改动,在所有情况下都不需要在 if 中将其转换为 (int),具体取决于枚举类型。但是,如果您将其直接转换为枚举类型本身,它应该始终有效。

【讨论】:

【参考方案7】:

针对 VB.NET 和 CLI 使用者,您可以像这样编译 char 枚举(最简单的方法是使用启用了 IL 支持(扩展)的 VB.NET 或 C# 项目):

.class public auto ansi sealed Hafner.Testing.EdgeCase.CharEnum
       extends [mscorlib]System.Enum

    .field public specialname rtspecialname char value__
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum Min = char(0)
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum Zero = char(0)
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum Max = char(65535)
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum DuplicateSameValue = char(65) //A
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum duplicateSameValue = char(65) //A
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum DuplicateOtherValue = char(90) //Z
    .field public static literal valuetype Hafner.Testing.EdgeCase.CharEnum duplicateOtherValue = char(88) //X


【讨论】:

【参考方案8】:

关于这一点,几乎所有的事情都已经说过了。只是想说如果你使用很多“字符枚举”,你可以使用扩展:

public enum MyEnum

    MY_VALUE = 'm'


public static class MyExtensions

    public static char GetChar(this Enum value)
    
        return (char)value.GetHashCode();
    


class Program

    public static void Main(string[] args)
    
        MyEnum me = MyEnum.MY_VALUE;
        Console.WriteLine(me + " = " + me.GetChar());
    

【讨论】:

您只需要(char)e。 You're incurring boxing penalty by going for enum.GetHashCode. 此外,GetHashCode 只是一个实现细节。【参考方案9】:

字符枚举只是字符串,不是吗?我不确定你会从字符枚举中获得什么其他好处?

正如其他人所说,枚举的默认类型是 int。

【讨论】:

从 NCHAR(0001) 和枚举的数据库列转换时很有用。具体来说,在选择中查看有意义的东西是有用的,但仅限于一组特定的值。例如:状态。待处理:'P',进行中:'I',成功完成:'S',失败:'F'。 我支持数据库评论,因为这正是导致我提出这个问题的原因。

以上是关于为啥我们不能有“char”枚举类型的主要内容,如果未能解决你的问题,请参考以下文章

java枚举类型enum用法

C语言中如何控制枚举类型占用空间的大小

java中的枚举类型指的是啥啊?

java里啥情况用枚举啊

C#如何将枚举类(enum)型转换成字符(string)类型

6-12 varchar和char 枚举类型enum 集合set