3

I'd need to store some properties of the enum's entries in their constants. For example indicate whether a color is cold or warm.

enum Colors
{
  Yellow, // warm
  Blue,   // cold
  Gray,   // cold
  Red,    // warm
  // etc.
}

In C++ I would define a macro to generate bitmasks for the constants. Something like:

#define WARM 1
#define COLD 0

#define MAKECOLOR(index, type) ((index << 8) | type)

enum Colors
{
  Yellow = MAKECOLOR(0, WARM),
  Blue   = MAKECOLOR(1, COLD),
  Gray   = MAKECOLOR(2, COLD),
  Red    = MAKECOLOR(3, WARM),
  // etc.
}

In C# this is not possible because there are no macros. I want to avoid writing bitmask expressions directly in the enum. Like this:

  ...
  Gray   = ((2 << 8) | 0),
  ...

Any ideas?

P.S.
Yes, I'm a syntactic sugar freak. :D

3 Answers 3

3

You should use attributes at the enum values. Read this article, it's pretty good:

http://www.codeproject.com/KB/cs/enumwithdescription.aspx

Hope it helps!

Sign up to request clarification or add additional context in comments.

3 Comments

Good idea. The only question is how fast is the evaluation of the attributes.
This solution does have the performance penalty of using reflection. If you want to include the property of each enumeration member in its value for speed, you might as well use a separate Warm/Cold array and use the enum member's integer value as index (e.g. warmcold[(int)Colors.Gray]. I think it is faster.
Well, they are accessed thru reflection so don't expect the speed of light.
2

I do tend to write the bit expression directly in the enum:

enum Colors
{
    Yellow = (0 << 8) | ColorTemp.Warm,
    Blue   = (1 << 8) | ColorTemp.Cold,
    Gray   = (2 << 8) | ColorTemp.Cold,
    Red    = (3 << 8) | ColorTemp.Warm,
}

enum ColorTemp
{
    Cold = 0,
    Warm = 1,
}

And then write a simple extension class at the bottom of the file, like this:

public static class ColorsExtensions
{
    public ColorTemp GetTemperature(this Colors color)
    {
        return (ColorTemp)(color & 0x01);
    }
}

2 Comments

This is how to acquire the property. Instead, I need a way to define it.
@armen: This is the only correct way to do it. Otherwise, it won't work.
0

In C#, enum need to have const values defined at compile-time. In sum, C# is more const than C++.

In C#, const is used to denote a compile-time constant expression. It'd be similar to this C++ code:

enum {
  count = buffer.Length;
}

Because buffer.Length is evaluated at runtime, it is not a constant expression, and so this would produce a compile error.

C# has a readonly keyword which is a bit more similar to C++'s const. (It's still much more limited though, and there is no such thing as const-correctness in C#).

const is meant to represent a compile-time constant... not just a read-only value.

You can't specify read-only but non-compile-time-constant local variables in C#, I'm afraid. Some local variables are inherently read-only - such as the iteration variable in a foreach loop and any variables declared in the first part of a using statement. However, you can't create your own read-only variables.

If you use const within a method, that effectively replaces any usage of that identifier with the compile-time constant value.

So, you are going to have to define your values at compile-time in your enum. They cannot be evaluated at run-time. Those are the rules.

4 Comments

Well, expressions like (3 << 8) | Warm are evaluated at compile-time. The difference between (3 << 8) | Warm and static function call is just a question of powerful optimizer.
@Vlad: I tried it in C# with a static function call and the compiler blew up complaining that it must be a constant. When I did it like @Virtlink did, it works because it is evaluated at compile-time in the enum.
This basically means that the language's optimizer is shy and doesn't want to show its full strength evaluating constant expressions at compile time, not that it's not possible at all. After all, the considered expression is a compile-time constant.
@Vlad: That's what I thought too except the compiler shipped with Visual Studio 2010 does not allow me to do this so that led me down the road that it simply is not possible with C# like it is with C++.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.