Flagged, typed, enumerations?

I

Ian Boyd

i want to have an enumeration that can also act as bit-flags, and have
values.

using System;
using System.Windows.Forms;
namespace MyProgram
{
class HelloEnumerations
{
[FlagsAttribute]
enum FlagColors : uint
{
Red = 0x01,
Green = 0x02,
Blue = 0x04,
}

public static void Main()
{
DoSomething(FlagColors.Red | FlagColors.Blue);
}

private static void DoSomething(uint theFlagColors)
{
System.Windows.Forms.MessageBox.Show(theFlagColors.ToString());
}
}
}

Problem is i get a compile error on the line:
DoSomething(FlagColors.Red | FlagColors.Blue);

saying "Argument '1': cannot convert from
'MyProgram.HelloEnumerations.FlagColors' to 'uint'"

Why can it not convert it to a uint? That's why i have the " : uint" in the
declaration of
enum FlagColors : uint

What magic keyword am i missing; and how to make it work without manually
casting to a (uint)?
 
J

Jose Durazo

My URL only takes you to a general location in the MSDN Library. The
specific location you can look at is Development Tools and Languages >
Visual Studio .NET > Visual Basic and Visual C# > Reference > Visual C#
Language > C# Language Specification > 6. Conversions, so it's a short and
sweet path :).

From there you'll see the sections I mentioned in my previous posting.

-Jose
 
M

Mattias Sjögren

What magic keyword am i missing; and how to make it work without manually
casting to a (uint)?

Why don't you simply change the parameter type in the DoSomething
method to FlagColors? You can't avoid the cast to uint otherwise,
unless you replace the enum with something like

static class FlagColors {
public const uint Red = 0x1;
public const uint Green = 0x2;
public const uint Blue = 0x4;
}


Mattias
 
D

Dave Sexton

Hi,

Type the argument as HelloEnumerations. That's one reason for using an Enum
in the first place as opposed to constants:

private static void DoSomething(HelloEnumerations flags)
{
...
}

IntelliSense in Visual Studio will make it much easier for you to call the
method if it accepts an Enum value instead of uint.
 
I

Ian Boyd

Why don't you simply change the parameter type in the DoSomething
method to FlagColors?

Because it's not my method, it's a PInvoke.
You can't avoid the cast to uint otherwise,
unless you replace the enum with something like

static class FlagColors {
public const uint Red = 0x1;
public const uint Green = 0x2;
public const uint Blue = 0x4;
}


So what's the point of having values next to enumeration values? They
obviously do have a numerical value associated with each one. And more
importantly, what's the point of the "uint" next to it?

To say that the compiler has no way of knowing what numerical values each
enumeration member corresponds to is just unrealistic. You mean to tell me
that after specifying "uint" and (1, 2, 4), the compiler has no information
whatsoever in the universe to figure out what uint value the enumeration
corresponds to?

The compiler obviously DOES know that FlagColors ARE uint's. i don't want
person calling to have to force a cast, the cast should obviously be done by
the compiler.


i realize i can't hope to see limitations to the C# language fixed; but at
least i can a Google record of this bug.
 
M

Marc Gravell

Try to understand; this is neither a limitation or a bug; this is the
deliberate and intentional design of the C# specification. As such, it
would be an *error* for the compiler to do this, as it doesn't comply
with the spec.
For what it is worth, I believe that zero (only) is allowed as an
automatic cast (presumably to make bitwise comparisons a lot less
verbose, since the default value would be handled separately to
compiled code), but nothing else.
And both the runtime and compiler *do* retain the knowledge of the
underlying type and value - it just doesn't allow *implicit* casting
between them. Personally I can't say that adding a cast has ever
caused me a moments trouble...

Marc
 
D

Dave Sexton

Hi Ian,

You can still take the advice in my original response. Declare even your
extern methods using an enum since the framework will automatically marshal
the underlying type.

A better design for P/Invoke anyway would be to create a managed wrapper
around it for consumers instead of them calling it directly.
 
M

Marc Gravell

As an alternative to casting, maybe you just need an overload here?
You have the PInvoke version that accepts a uint... so you can just
add:

public static void DoSomething(FlagColors colors) {
DoSomething((unit) colors);
}

And now you can call DoSomething(FlagColors.Red);
etc

Marc
 
M

Marc Gravell

(oh - and in line with Dave's reply of a few moments ago - you could
mark the PInvoke [uint] version as private, so only the enum version
is public)
 
I

Ian Boyd

You can still take the advice in my original response. Declare even your
extern methods using an enum since the framework will automatically
marshal the underlying type.

Really? The compiler will perform an implicit cast for me?

Well okay then. That's what i was after in the first place!

A better design for P/Invoke anyway would be to create a managed wrapper
around it for consumers instead of them calling it directly.

Just so i understand what you're saying:

i write a class with "prettier" methods; and those methods in turn do the
"ugly" P/Invoke? And either way i'm still writing the code to do the
PInvoke, except that the buck stops here, as it were?
 
I

Ian Boyd

(oh - and in line with Dave's reply of a few moments ago - you could mark
the PInvoke [uint] version as private, so only the enum version is public)

i like all the ideas.

ty all vm
 
D

Dave Sexton

Hi Ian,
Really? The compiler will perform an implicit cast for me?

Well okay then. That's what i was after in the first place!

Really! :)

Although the compiler isn't performing any cast, it's the Marshal class that
does all the work at runtime, AFAIK.
Just so i understand what you're saying:

i write a class with "prettier" methods; and those methods in turn do the
"ugly" P/Invoke? And either way i'm still writing the code to do the
PInvoke, except that the buck stops here, as it were?

Yep.

Take a look at the source code for the Framework Class Libraries using a
tool like ILDasm or .NET Reflector. You'll see that a good portion of the
framework is really just P/Invoke wrappers. Take a look at the
System.Windows.Forms assemby, for instance.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top