Reflection - integer values directly to enum

T

tobiwan_kenobi

The following code is in a custom deserializer:

object value = (int) 1;
string nameToParse = Enum.GetName(field.FieldType, value);
value = Enum.Parse(field.FieldType, nameToParse);

Currently we follow the path below:

intValue --> enum name --> enum value

Is there any way in reflection to do:

intValue --> enum value
 
C

Chris Shepherd

tobiwan_kenobi said:
The following code is in a custom deserializer:

object value = (int) 1;
string nameToParse = Enum.GetName(field.FieldType, value);
value = Enum.Parse(field.FieldType, nameToParse);

Currently we follow the path below:

intValue --> enum name --> enum value

Is there any way in reflection to do:

intValue --> enum value

You can cast to the enum from an int, can't you?

This scenario has always worked for me:
public enum TestEnum
{
One = 1,
Two
}

public TestMyEnum()
{
TestEnum a = (TestEnum)1;
TestEnum b = (TestEnum)2;

Console.WriteLine("A: " + a.ToString() + "\nB: " + b.ToString());
}


Chris.
 
J

Jon Skeet [C# MVP]

Chris Shepherd said:
You can cast to the enum from an int, can't you?

Only if you know the enum type at compile time - which it looks like
the OP doesn't.

Unfortunately Convert.ChangeType doesn't work, which was my first
thought. I suspect that using Expression.Convert would work with a bit
of work, but unfortunately dinner is calling me. Time for Marc to take
over, I'd say :)

(Seriously, there must be a better way, but I don't know it offhand...)
 
T

tobiwan_kenobi

No, in this situation we can't cast because we are using reflection to write
a general routine that will create an instance of any enum that needs to get
deserialized, so we don't know which enum it is. The type of enum is
recovered from the XML document at deserialization time.
 
L

Lasse Vågsæther Karlsen

tobiwan_kenobi said:
No, in this situation we can't cast because we are using reflection to write
a general routine that will create an instance of any enum that needs to get
deserialized, so we don't know which enum it is. The type of enum is
recovered from the XML document at deserialization time.

What about:

Object value = (int) 1;
value = Enum.Parse(field.FieldType, value.ToString());
 
T

tobiwan_kenobi

Lasse Vågsæther Karlsen said:
What about:

Object value = (int) 1;
value = Enum.Parse(field.FieldType, value.ToString());

Besides not wanting to convert an int to a string to an enum for performance
reasons, it just doesn't work. We tried this and the above would give the
following:

1 --> "1" --> then fail (because "1" is not one of the names in the enum)
 
L

Lasse Vågsæther Karlsen

tobiwan_kenobi said:
Besides not wanting to convert an int to a string to an enum for performance
reasons, it just doesn't work. We tried this and the above would give the
following:

1 --> "1" --> then fail (because "1" is not one of the names in the enum)

That's odd:

using System;

public class MyClass
{
public enum Test
{
A = 5,
B = 7,
C = 10,
D = 15
}

public static void Main()
{
for (Int32 index = 0; index <= 20; index++)
Console.WriteLine(index + " = " + Enum.Parse(typeof(Test),
index.ToString()));
Console.ReadLine();
}
}

Tested this in Snippet Compiler on .NET 2.0 SP1 and 3.5, and both
produced the following:

0 = 0
1 = 1
2 = 2
3 = 3
4 = 4
5 = A <-- here
6 = 6
7 = B <-- here
8 = 8
9 = 9
10 = C <-- here
11 = 11
12 = 12
13 = 13
14 = 14
15 = D <-- here
16 = 16
17 = 17
18 = 18
19 = 19
20 = 20

As you can see, the enums corresponding to values are correctly parsed
from the string, even though the string is just a number.

In any case, if performance is an issue you won't gain much by mine or
your methods, in both cases you're involving a string.

You can only cast an int to an enum if you know the enum, if all you
have is a Type object, you need to muck about like you or I have done,
and if that doesn't produce fast enough code, well, you're out of luck.

However, let's put aside the current problem for a second.

What specifically is it that you're doing? If you're mucking around with
reflection and custom serialization, are you ultimately going to write
the value into a field or property of that enum type?

In other words, like this?

using System;
using System.Reflection;

public class MyClass
{
public enum Test
{
A = 5,
B = 7,
C = 10,
D = 15
}

public Test TestField = Test.D;

public static void Main()
{
MyClass mc = new MyClass();
FieldInfo fi = mc.GetType().GetField("TestField");
fi.SetValue(mc, 5);
Console.WriteLine(mc.TestField);
Console.ReadLine();
}
}

The output is A (which corresponds to the 5).

As you can see, I write the integer directly into the property. I assume
some conversion is taking place under the hood, but perhaps this has
less overhead than the code we've looked at so far?
 
T

tobiwan_kenobi

Apparently it was different problem. We were reading the information in from
the database and were getting casting errors.

The SetValue using the value from the database was returning a casting
error. SetValue does not give me this error on the value returned from
Enum.ToObject. Since casting values from the database is very picky about
how it is done, Enum.ToObject seems to be the best choice.
 
L

Lasse Vågsæther Karlsen

tobiwan_kenobi said:
Apparently it was different problem. We were reading the information in from
the database and were getting casting errors.

Then you didn't have an int, you had something else.

This is why it is important for you to post everything you know about a
problem, or, to verify that the code you give us really exhibit the
problems you say it does.

Otherwise we'll post numerous answers or tips which really doesn't help
your real problem at all.
 
T

tobiwan_kenobi

Yes, it was in int64, but I can't depend on any particular type coming back
from the database. That's another reason not to cast. Plus multiple casts
are sometimes required. Because it is a database type int64, it won't cast
directly to an system.int32, you have to do a cast like '(int)(long) value'
for it not to give a casting error.
 
T

tobiwan_kenobi

Lasse Vågsæther Karlsen said:
This is why it is important for you to post everything you know about a
problem, or, to verify that the code you give us really exhibit the
problems you say it does.

Sometimes one can't be sure what is relevant.
Otherwise we'll post numerous answers or tips which really doesn't help
your real problem at all.

I figured out a solution by myself, but thanks to all for the posts. I
learned about 12 other things.
 

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