43

I want to know why we can't have "char" as underlying enum type. As we have byte,sbyte,int,uint,long,ulong,short,ushort as underlying enum type. Second what is the default underlying type of an enum?

Guillermo Gutiérrez
  • 17,273
  • 17
  • 89
  • 116
Praveen Sharma
  • 4,511
  • 7
  • 27
  • 17

9 Answers9

84

I know this is an older question, but this information would have been helpful to me:

It appears that there is no problem using char as the value type for enums in C# .NET 4.0 (possibly even 3.5, but I haven't tested this). Here's what I've done, and it completely works:

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

Convert Enum to char:

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

Convert char to Enum:

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

Works like a charm, just as you would expect from the char type!

kad81
  • 10,712
  • 3
  • 38
  • 44
  • 9
    upvoted your answer, but be aware the enum in answer still has got `int` as the underlying type. Compiler treats it as `int`. Wished C# didnt have this edge case. – nawfal May 27 '15 at 15:27
  • 2019 comment - If you are relying on the underlying .ToString() call it is actually taking "NotPaid" and "Paid" and you may have a scenario that is auto truncation or taking just the first character of the Name - which by coincidence is the same as the Char you see "Paid" = 'P' "NotPaid" = 'N' MyEnum = 'Z' would return 'M' for example – Sql Surfer Sep 21 '19 at 02:07
15

The default type is int. More information at the C# reference at MSDN. You can also find a link to the C# language specification at MSDN. I think the reason for the restriction probably derives from these statements in the language specification, section 4.1.5.

The char type is classified as an integral type, but it differs from the other integral types in two ways:

• There are no implicit conversions from other types to the char type. In particular, even though the sbyte, byte, and ushort types have ranges of values that are fully representable using the char type, implicit conversions from sbyte, byte, or ushort to char do not exist.

• Constants of the char type must be written as character-literals or as integer-literals in combination with a cast to type char. For example, (char)10 is the same as '\x000A'.

Community
  • 1
  • 1
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
13

This is workaround I'm using

enum MyEnum
{
    AA = 'A',
    BB = 'B',
    CC = 'C'
};

static void Main(string[] args)
{
    MyEnum e = MyEnum.AA;
    char value = (char)e.GetHashCode(); //value = 'A'
}
Emir
  • 1,586
  • 3
  • 16
  • 32
  • 6
    Or you could just write `(char) e` without the `GetHashCode()`. – Roman Starkov Mar 27 '13 at 02:03
  • 4
    All you need is `(char)e`. [You're incurring boxing penalty by going for `enum.GetHashCode`.](http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp) – nawfal Dec 01 '13 at 20:04
3

Technically, you can't do this. But, you can convert the enum to a byte and then convert that to char. This is useful if your goal is to have something like this (realizing this is impossible to do:

public enum CharEnum
{
    one = '1'
}

You can do this, however, by using ASCII byte values and then converting:

public enum CharEnum
{
    one = 49,
    two = 50
}

You can then convert to byte and to char to get the char value. It is not really pretty, but it will work, if getting a char is your ultimate goal. You can also use unicode and an int value, if you need chars outside of the ASCII range. :-)

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
Gregory A Beamer
  • 16,870
  • 3
  • 25
  • 32
1

See ECMA standard 335, Common Language Infrastructure (CLI), in Ecma International. The CLI allows the underlying type to be char or bool but C# and VB.Net don't allow it. For what it is worth, C++/CLI does allow System::Char as the underlying type.

I presume that C# and VB.Net don't allow char and bool as the underlying type for syntactical reasons only.

Sam Hobbs
  • 2,594
  • 3
  • 21
  • 32
  • C++ `char` is not the same as C# `char`, it's the same as C# `sbyte` (which is an allowed base type for enums) – Ben Voigt May 12 '18 at 16:04
  • @BenVoigt you are correct that an underlying type of System.Char won't work in C# even if it is defined in C++/CLI. System.Char does work as an underlying type if it is all C++/CLI so I will change my response since it adds to the understanding. – Sam Hobbs May 12 '18 at 16:45
  • @BenVoigt: An IL defined enum of char can't be consumed by C# but can by VB.NET (same with a boolean enum whereas they don't make any sense without some form of automatic negation of false-entries as otherwise they would read `if (!BoolEnum.Disabled)` to ask whether the entry _is_ disabled.). – Christoph Nov 10 '19 at 17:43
  • @Christoph: No different from `if (!false)`... in practice, the constant wouldn't appear in a conditional control expression, you would instead have `var x = BoolEnum.Disabled; if (!x) ... ` and that seems 100% normal. – Ben Voigt Nov 11 '19 at 22:59
  • @BenVoigt: You are right, if one uses them correctly like in `var enabled = BoolEnum.Disabled; if (!enabled) ...` everything is clear, also in `var state = BoolEnum.Disabled; if (state == BoolEnum.Disabled)` it works. I tried it once out in VB.NET and thought it was totally confusing `If Not BoolEnum.Disabled Then` to ask whether it is disabled, but you are right, one refers usually to a variable and not the constant. Let's introduce them in C# and VB.NET, they are already in CLI since 1.0! – Christoph Nov 12 '19 at 17:50
0
char charPC = 'P';
if (Enum.IsDefined(typeof(PayCode), (PayCode)charPC)) { 
        // check if charPC is a valid value
        PayCode enumPC = (PayCode)charPC; // enumPC == PayCode.Paid
}
  • Made a small change, no need to convert it to an (int) in the if for all cases, depends on the enum type. But if you cast it directly to the enum type itself, it should always work.
parik
  • 2,313
  • 12
  • 39
  • 67
Mike
  • 1,525
  • 1
  • 14
  • 11
0

Targeting VB.NET and CLI consumers, you can compile the char enum like this (easiest with a VB.NET or C# project that has IL Support (an extension) enabled):

.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

}
Christoph
  • 3,322
  • 2
  • 19
  • 28
-1

Pretty much everything has been said already about that. Just wanted to say you can use extensions if you use a lot of "char enums":

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());
    }
}
laurian
  • 739
  • 6
  • 18
  • 1
    All you need is `(char)e`. [You're incurring boxing penalty by going for `enum.GetHashCode`.](http://stackoverflow.com/questions/7995606/boxing-occurrence-in-c-sharp) Furthermore, `GetHashCode` is merely an implementation detail. – nawfal Dec 01 '13 at 20:13
-5

Character enums would simply be strings wouldn't they? I'm not sure what other benefit you would derive from a character enumeration?

As others have said, the default type is int for an enumeration.

Jeffrey Cameron
  • 9,975
  • 10
  • 45
  • 77
  • 2
    It is useful when converting from a database column that is a NCHAR(0001) and the enum. Specifically, it is useful to have something that makes sense when looking at it in a select, but is limited to a specific set of values. As an example: Status. Pending: 'P', In Progress: 'I', Completed Successfully: 'S', Failed: 'F'. – David Beckman Feb 20 '12 at 22:11
  • 1
    I second the database comment as that is exactly what lead me to this question. – Nathan Nov 17 '17 at 22:27