An elegant way to get string from enum value? [duplicate] - c#

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is there a simple script to convert C++ enum to string?
In the C# program below, while using enumeration Priority, i need the string "None" and not the id 0. The C# code for doing this is given below. Is there an elegant way of doing this in C++. Can a map be avoided in the C++ implementation.
enum Priority
{
None,
Trivial,
Normal,
Important,
Critical
}
class Program
{
static void Main()
{
// Write string representation for Important.
Priority enum1 = Priority.Important;
string value1 = enum1.ToString();
// Loop through enumerations and write string representations. (See GetNames)
for (Priority enum2 = Priority.None; enum2 <= Priority.Critical; enum2++)
{
string value2 = enum2.ToString();
Console.WriteLine(value2); //outputs the string None, Trivial etc ...
}
}
}
public override string ToString()
{
Type type = base.GetType();
object obj2 = ((RtFieldInfo)GetValueField(type)).InternalGetValue(this, false);
return InternalFormat(type, obj2);
}

In C++, an enum is nothing more than a bit of syntactic sugar around an integral literal. The compiler quickly strips the enumerator name away, so the runtime never has access to it. If you want to have a string name for an enum, you have to do it the hard way.

Related

string to Enum in c# [duplicate]

This question already has answers here:
Search for a string in Enum and return the Enum
(13 answers)
Closed 9 years ago.
I need to assign a string to a Enum value. My scenario and code below
Am accessing a webservice method say addWhere(int i ,int j,Comparison)
Where Comparison is of type Enum.
Am fetching value from UI and having it in a string
string strComparison= "AND"; or
string strComparison= "OR"
i need to set these values to ENUM. I tried the below code
addWhere(2 ,3,Enum.Parse(typeof(Comparison),strComparison))
But didnt worked. What is the way to solve this or any alternate methods ?
Thanks
Looks like your missing the return cast i.e.
(Comparison)Enum.Parse(typeof(Comparison), strComparison);
Enum.Parse returns an object were as your addWhere method is expecting a Comparison type value.
You must cast the result of Enum.Parse to the correct type:
addWhere(2, 3, (Comparison)Enum.Parse(typeof(Comparison), strComparison));
You can do something like:
Comparison comparison;
if(Comparison.TryParse(strComparison, out comparison))
{
// Work with the converted Comparison
}
As said in earlier posts, you might be missing type casting.
enum Comparision
{
AND,
OR
}
class Program
{
static void Main(string[] args)
{
Comparision cmp = (Comparision)Enum.Parse(typeof (Comparision), "And", true);
Console.WriteLine(cmp == Comparision.OR );
Console.WriteLine(cmp == Comparision.AND);
}
}

Casting string to enum [duplicate]

This question already has answers here:
Convert a string to an enum in C#
(29 answers)
Closed 8 years ago.
I'm reading file content and take string at exact location like this
string fileContentMessage = File.ReadAllText(filename).Substring(411, 3);
Output will always be either Ok or Err
On the other side I have MyObject which have ContentEnum like this
public class MyObject
{
public enum ContentEnum { Ok = 1, Err = 2 };
public ContentEnum Content { get; set; }
}
Now, on the client side I want to use code like this (to cast my string fileContentMessage to Content property)
string fileContentMessage = File.ReadAllText(filename).Substring(411, 3);
MyObject myObj = new MyObject ()
{
Content = /// ///,
};
Use Enum.Parse().
var content = (ContentEnum)Enum.Parse(typeof(ContentEnum), fileContentMessage);
As an extra, you can take the Enum.Parse answers already provided and put them in an easy-to-use static method in a helper class.
public static T ParseEnum<T>(string value)
{
return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
}
And use it like so:
{
Content = ParseEnum<ContentEnum>(fileContentMessage);
};
Especially helpful if you have lots of (different) Enums to parse.
.NET 4.0+ has a generic Enum.TryParse
ContentEnum content;
Enum.TryParse(fileContentMessage, out content);
Have a look at using something like
Enum.TryParse
Converts the string representation of the name or numeric value of one
or more enumerated constants to an equivalent enumerated object. A
parameter specifies whether the operation is case-sensitive. The
return value indicates whether the conversion succeeded.
or
Enum.Parse
Converts the string representation of the name or numeric value of one
or more enumerated constants to an equivalent enumerated object.

Building generic method for List<Enum>

In my application, I have something like:
public enum Locations {
LocationA,
LocationB,
LocationC
}
private List<Locations> _myLocations;
public Int64 PackedLocations {
get {
return PackEnumList(this._myLocations);
}
}
So: an enum (backed by int), a List of those enum values, and a read-only property which returns the result of a method I've left out so far.
That method, PackEnumList, is meant to give me a 64-bit integer where each BIT denotes whether the corresponding enum value was selected or not in a list of unique enum values. So in my example above, if _myLocations has only one item: {Locations.LocationA}, the result would be 1 (binary: ...00001), if we then add Locations.LocationC to that list, the result would be 5 (binary: ...000101). The implementation isn't important right now (but I'll include it below for completion/interest/feedback), but the signature of that method is:
public Int64 PackEnumList(List<Enum> listOfEnumValues) {
...
}
When I compile, I get an error that "the best overloaded method ... has some invalid arguments".
I'm guessing this is because _myLocations is being seen as a List of int values, but I'd like PackEnumList() to work even if the enumeration being used were backed by something else, if possible.
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
For completeness, here's the rest of what I'm trying to do (these are static because they're in a shared utility class). These are completely untested yet (since I can't get past the compile error when calling the pack method), so take them with a grain of salt. And there might be a better way to do this, I'm doing this half to solve an interesting problem, and half because I think it is an interesting problem.
public static Int64 PackEnumList(List<Enum> listOfEnumValues) {
BitArray bits = new BitArray(64, defaultValue: false);
foreach (var value in listOfEnumValues) {
// get integer value of each Enum in the List:
int val = Convert.ToInt32(value);
if (val >= 64) {
// this enum has more options than we have bits, so cannot pack
throw new Exception("Enum value out of range for packing: " + val.ToString());
}
bits[val] = true;
}
var res = new Int64[1];
bits.CopyTo(res, 0);
return res[0];
}
// (this method is a little farther from the ideal: the resulting list will need
// to be matched by the caller to the appropriate List of Enums by casting
// each Int32 value to the Enum object in the list)
public static List<Int32> UnpackEnumList(Int64 packedValue) {
string binaryString = Convert.ToString(packedValue, 2);
List<Int32> res = new List<Int32>();
for (int pos = 0; pos < binaryString.Length; pos++) {
if (binaryString[binaryString.Length - pos - 1] == '1') {
// bit is on
res.Add(pos);
}
}
return res;
}
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
Within straight C#? Nope. But you can fudge it...
I have a project called Unconstrained Melody which allows you to make a generic method with a constraint of "T must be an enum type" or "T must be a delegate type". These are valid constraints at the IL level, but can't be expressed in C#
Basically Unconstrained Melody consists of two parts:
A library of useful methods with those constraints, where the source code is written using valid C# which doesn't actually represent those constraints, but uses a marker interface
An IL-rewriting project (ugly but servicable) which converts those constraints into the real "unspeakable" ones
(The expectation is that users of the library would just use the rewritten binary.)
It sounds like you could use the latter part of the project for your code here. It won't be terribly pleasant, but it would work. You might also find the library part useful.
As a side thought, you might want to consider using a [Flags]-style enum instead:
[Flags]
public enum Locations {
LocationA = 1 << 0,
LocationB = 1 << 1,
LocationC = 1 << 2
}
Change your method signature to public Int64 PackEnumList(IEnumerable<Enum> listOfEnumValues)
And then call it like following:
public Int64 PackedLocations
{
get { return PackEnumList(this._myLocations.Cast<Enum>()); }
}
A List<Enum> is not a List<Locations> nor a List<Int32>. Use a generic method to handle the list:
public static void PackEnumList<T>(IEnumerable<T> list) where T : IConvertible
{
foreach (var value in list)
int numeric = value.ToInt32();
// etc.
}
I'd change your signature method to:
public Int64 PackEnumList<T>(IEnumerable<T> listOfEnumValues) where T : struct, IFormattable, IConvertible {
...
}
The where T : struct... constrains it to enum types only (any any other struct implementing both interfaces, which is probably very low)

The correct way of casting an int to an enum [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Cast int to Enum in C#
I fetch a int value from the database and want to cast the value to an enum variable. In 99.9% of the cases, the int will match one of the values in the enum declaration
public enum eOrderType {
Submitted = 1,
Ordered = 2,
InReview = 3,
Sold = 4,
...
}
eOrderType orderType = (eOrderType) FetchIntFromDb();
In the edge case, the value will not match (whether it's corruption of data or someone manually going in and messing with the data).
I could use a switch statement and catch the default and fix the situation, but it feels wrong. There has to be a more elegant solution.
Any ideas?
You can use the IsDefined method to check if a value is among the defined values:
bool defined = Enum.IsDefined(typeof(eOrderType), orderType);
You can do
int value = FetchIntFromDb();
bool ok = System.Enum.GetValues(typeof(eOrderType)).Cast<int>().Contains(value);
or rather I would cache the GetValues() results in a static variable and use it over and over gain.

C# int to enum conversion [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Cast int to enum in C#
If I have the following code:
enum foo : int
{
option1 = 1,
option2,
...
}
private foo convertIntToFoo(int value)
{
// Convert int to respective Foo value or throw exception
}
What would the conversion code look like?
It's fine just to cast your int to Foo:
int i = 1;
Foo f = (Foo)i;
If you try to cast a value that's not defined it will still work. The only harm that may come from this is in how you use the value later on.
If you really want to make sure your value is defined in the enum, you can use Enum.IsDefined:
int i = 1;
if (Enum.IsDefined(typeof(Foo), i))
{
Foo f = (Foo)i;
}
else
{
// Throw exception, etc.
}
However, using IsDefined costs more than just casting. Which you use depends on your implemenation. You might consider restricting user input, or handling a default case when you use the enum.
Also note that you don't have to specify that your enum inherits from int; this is the default behavior.
I'm pretty sure you can do explicit casting here.
foo f = (foo)value;
So long as you say the enum inherits(?) from int, which you have.
enum foo : int
EDIT Yes it turns out that by default, an enums underlying type is int. You can however use any integral type except char.
You can also cast from a value that's not in the enum, producing an invalid enum. I suspect this works by just changing the type of the reference and not actually changing the value in memory.
enum (C# Reference)
Enumeration Types (C# Programming Guide)
Casting should be enough. If you're using C# 3.0 you can make a handy extension method to parse enum values:
public static TEnum ToEnum<TInput, TEnum>(this TInput value)
{
Type type = typeof(TEnum);
if (value == default(TInput))
{
throw new ArgumentException("Value is null or empty.", "value");
}
if (!type.IsEnum)
{
throw new ArgumentException("Enum expected.", "TEnum");
}
return (TEnum)Enum.Parse(type, value.ToString(), true);
}
if (Enum.IsDefined(typeof(foo), value))
{
return (Foo)Enum.Parse(typeof(foo), value);
}
Hope this helps
Edit
This answer got down voted as value in my example is a string, where as the question asked for an int. My applogies; the following should be a bit clearer :-)
Type fooType = typeof(foo);
if (Enum.IsDefined(fooType , value.ToString()))
{
return (Foo)Enum.Parse(fooType , value.ToString());
}
You don't need the inheritance. You can do:
(Foo)1
it will work ;)

Categories

Resources