tags:

views:

475

answers:

2

We have legacy character codes that we want to store as numbers in a new system. To increase readibility and general understanding in the code for devs making the migration, I want to do Enums like this...

Public Enum Status As Short
    Open = AscW("O")
    Closed = AscW("C")
    Pending = AscW("P")
    EnRoute = AscW("E")
End Enum

With this setup, the code will be readable (imagine If Record.Status = Status.Open), and yet the values will be stored in the database as small numbers so it will be efficient. However... I am a VB.NET guy, but everybody wants to code in C#, so I need this sort of structure in C#.

After Googling, I discovered the the general .NET equivalent of AscW is Convert.ToInt32("C"). When I try to use that statement in an enum, I get the compiler error "Constant Expression Required".

How can I do this in C#? Is there a better way?

+10  A: 

A method call is not a constant expression. Try this:

public enum Status { 
   Open = 'O',
   Closed = 'C',
   Pending = 'P',
   EnRoute = 'E'
}

The reason AscW works in VB is that it's an internal thing that VB compiler understands and evaluates at compile time and is considered a constant expression by the compiler. Even in VB, Convert.ToInt32 will not work.

To quote the Visual Basic specification:

11.2 Constant Expressions

A constant expression is an expression whose value can be fully evaluated at compile time. [...] The following constructs are permitted in constant expressions:

[...]

  • The following run-time functions:

    • Microsoft.VisualBasic.Strings.ChrW
    • Microsoft.VisualBasic.Strings.Chr, if the constant value is between 0 and 128
    • Microsoft.VisualBasic.Strings.AscW, if the constant string is not empty
    • Microsoft.VisualBasic.Strings.Asc, if the constant string is not empty
Mehrdad Afshari
Well I guess it could not be much easier than this :) Thank you!
Josh Stodola
+1 and accepted, especially because you included *why* my sample code works in VB. Thank you, Mehrdad.
Josh Stodola
It understands AscW because there is an automatic references to the Microsoft.VisualBasic namespace in the default projects settings of every Visual Basic project by default which C# does not have. This is used for easy conversion of old VB6 applications.
Nick
Nick: It doesn't really matter that it's declared in `Microsoft.VisualBasic`. The key thing is the compiler is hard-wired to understand `AscW` and it's not really calling any methods at run time. It just replaces the expression with its integral value at compile time.
Mehrdad Afshari
+1, It's *slightly* more complicated than that. AscW is both well understood by the compiler and a feature of the VB runtime. In the case of a constant and valid expression, the compiler will optimize out the AscW call. But in cases where it's not constant or not understood, it will defer to the VB runtime.
JaredPar
@JaredPar: Yeah, of course, if the argument is constant, the value cannot be replaced at compile time. The point is, as you said, the runtime function is irrelevant here. By the way, I don't think it really counts as an "optimization" since the spec clearly requires this behavior.
Mehrdad Afshari
I did want to add that I find it somewhat disturbing that I am unable to use string constants like this in VB. I get the error "Conversion from String to Short cannot occur in a constant expression". Then I tried a Char literal, that also does not work (similiar message). I guess it must've been easier to plug the compiler for `AscW` then for literals :D
Josh Stodola
@Josh: VB.NET (unlike C#) does not support implicit coercions from character to integers. This design decision makes simply writing "`EnumMember = "A"c` not work. It's not really a matter of ease of implementation.
Mehrdad Afshari
+3  A: 

Try this:

public enum Status
{
    Open    = 'O',
    Closed  = 'C',
    Pending = 'P',
    EnRoute = 'E'
}
Rubens Farias
Thank you, yes I will up-vote this too becuase there was only seconds apart in your answers. You guys are *fast*!
Josh Stodola