Get enum value as string - c#

I have an enum like this:
enum myEnum
{
a = 0101,
b = 2002,
c = 0303
}
I try to get enum value with casting but the 0 at the begin of my enums was removed.
For example I tried this:
var val = (int)myEnum.a;
How can get enum value as string when we have 0 at the beginning of it?

You should rethink your design, but if you want to check your enum integers to a given string, you can use .ToString("0000") to get the string "0101" out of the integer 101.

First, enums are integers, since as their name says, they are enumerations and an enumeration, they are numbers, so enum is integer.
Secondly, you must bear in mind that zero is a null value, since the system is a 01 or 001 like 1, since (basic mathematics) a zero to the left is worthless, so this code is incorrect.
enum myEnum
{
a=0101,
b=2002,
c=0303,
}
The correct way is
enum myEnum
{
a = 0,
b = 1,
c = 2
}
Where the zero is alone, so the system sees it as an index
Now with this, you should only use one of the conversion processes of C#
string strOne = ((myEnum)0).ToString();
string strTwo = ((myEnum)1).ToString();
string strThree = ((myEnum)2).ToString();
Read the MSDN reference https://msdn.microsoft.com/en-us/library/16c1xs4z(v=vs.110).aspx

Enumeration values are always integers. If you need to associate a string with an enumeration value, you can use a dictionary:
enum myEnum { a, b, c }
Dictionary<myEnum, string> lookup = new Dictionary
{
{ a, "0101" },
{ b, "2002" },
{ c, "0303" }
};
To get the string associated with a particular value just use this:
var s = lookup[myEnum.a]; // s = 0101
Another common way to handle this sort of problem is simply to use constants.
class MyConstants
{
public const string a = "0101";
public const string b = "2002";
public const string c = "0303";
}
var s = MyConstants.a; // s = 0101

Try using formatting: you want 4 digits and that's why you can put d4 format string. In order to hide all these implmentation details (cast and formatting) let's write an extension method:
enum myEnum {
a = 0101,
b = 2002,
c = 0303
}
static class myEnumExtensions {
public static string ToReport(this myEnum value) {
return ((int)value).ToString("d4"); // 4 digits, i.e. "101" -> "0101"
}
}
...
myEnum test = myEnum.a;
Console.Write(test.ToReport());

If you always need a specific number of digits you could use string format to get the leading zeros:
var str = String.Format("{0:0000}", (int)myEnum.a);
Or, shorter:
var str = $"{(int) myEnum.a:D4}";
Alternative:
Use an attribute to add extra information to an enum
Attribute:
public class DescriptionAttribute : Attribute
{
public string Name { get; }
public DescriptionAttribute(string name)
{
Name = name;
}
}
Enum:
enum myEnum
{
[Description("0101")]
a = 101,
[Description("2002")]
b = 2002,
[Description("303")]
c = 303
}
Extension Method:
public static string GetDescription(this myEnum e)
{
var fieldInfo = e.GetType().GetField(e.ToString());
var attribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() as DescriptionAttribute;
return attribute.Name;
}
Usage:
var name = myEnum.a.GetDescription() //will return '0101'

Assuming that the numbers in your enum always have a length of 4
you can use the following
var val = (int)myEnum.a).ToString().PadLeft(4, '0')

Related

FluentAssertions 6 ObjectGraph compare Enum to String

With FluentAssertions 6 it seems you can longer verify if in a object graph if an Enum is equivalent to a string. Source: https://fluentassertions.com/upgradingtov6
enum MyEnum {
A,
B
}
class Source {
MyEnum Enum { get;set;}
}
class Expectation {
string Enum { get;set;}
}
var source = new Source() { Enum = MyEnum.A };
var expectation = new Expectation() {Enum = "A"};
//With V6 this assertion will fail but in V5 it will pass
expectation.Should().BeEquivalentTo(source, options => options.ComparingEnumsByName());
How can I assert the objects above with FluentAssertions? The behaviour I want is for the assertions to be made on the ToString representation of the enum.
As I side note, I get different behaviour when I swap the expectation with source. Shouldn't they be equivalent?
You can define a more relaxed equivalency step to handle string/enum comparisons.
class RelaxedEnumEquivalencyStep : IEquivalencyStep
{
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator)
{
if (comparands.Subject is string subject && comparands.Expectation?.GetType().IsEnum == true)
{
AssertionScope.Current
.ForCondition(subject == comparands.Expectation.ToString())
.FailWith(() =>
{
decimal? subjectsUnderlyingValue = ExtractDecimal(comparands.Subject);
decimal? expectationsUnderlyingValue = ExtractDecimal(comparands.Expectation);
string subjectsName = GetDisplayNameForEnumComparison(comparands.Subject, subjectsUnderlyingValue);
string expectationName = GetDisplayNameForEnumComparison(comparands.Expectation, expectationsUnderlyingValue);
return new FailReason(
$"Expected {{context:string}} to be equivalent to {expectationName}{{reason}}, but found {subjectsName}.");
});
return EquivalencyResult.AssertionCompleted;
}
if (comparands.Subject?.GetType().IsEnum == true && comparands.Expectation is string expectation)
{
AssertionScope.Current
.ForCondition(comparands.Subject.ToString() == expectation)
.FailWith(() =>
{
decimal? subjectsUnderlyingValue = ExtractDecimal(comparands.Subject);
decimal? expectationsUnderlyingValue = ExtractDecimal(comparands.Expectation);
string subjectsName = GetDisplayNameForEnumComparison(comparands.Subject, subjectsUnderlyingValue);
string expectationName = GetDisplayNameForEnumComparison(comparands.Expectation, expectationsUnderlyingValue);
return new FailReason(
$"Expected {{context:enum}} to be equivalent to {expectationName}{{reason}}, but found {subjectsName}.");
});
return EquivalencyResult.AssertionCompleted;
}
return EquivalencyResult.ContinueWithNext;
}
private static string GetDisplayNameForEnumComparison(object o, decimal? v)
{
if (o is null)
{
return "<null>";
}
if (v is null)
{
return '\"' + o.ToString() + '\"';
}
string typePart = o.GetType().Name;
string namePart = o.ToString().Replace(", ", "|", StringComparison.Ordinal);
string valuePart = v.Value.ToString(CultureInfo.InvariantCulture);
return $"{typePart}.{namePart} {{{{value: {valuePart}}}}}";
}
private static decimal? ExtractDecimal(object o)
{
return o?.GetType().IsEnum == true ? Convert.ToDecimal(o, CultureInfo.InvariantCulture) : null;
}
}
If it's just for a single test
var source = new Source() { Enum = MyEnum.A };
var expectation = new Expectation() { Enum = "A" };
expectation.Should().BeEquivalentTo(source, options => options.Using(new RelaxedEnumEquivalencyStep()));
source.Should().BeEquivalentTo(expectation, options => options.Using(new RelaxedEnumEquivalencyStep()));
Or if you want this globally you can set this using AssertionOptions.AssertEquivalencyUsing.
For MSTest put it in AssemblyInitialize.
For Xunit, see the documentation or use this Module Initializer example.
AssertionOptions.AssertEquivalencyUsing(e => e.Using(new RelaxedEnumEquivalencyStep()));
var source = new Source() { Enum = MyEnum.A };
var expectation = new Expectation() { Enum = "A" };
expectation.Should().BeEquivalentTo(source);
source.Should().BeEquivalentTo(expectation);
For completeness here are examples of the failure message when MyEnum and string do not match.
Expected property root.Enum to be equivalent to "B", but found MyEnum.A {value: 0}.
Expected property source.Enum to be <null>, but found MyEnum.B {value: 1}.
Expected property root.Enum to be equivalent to MyEnum.A {value: 0}, but found "B".
Expected property expectation.Enum to be equivalent to MyEnum.B {value: 1}, but found <null>.
Your expectation defines the Enum property as being a string, and the options you provide are used to instruct FA how the members of the expectation should be compared to the subject. So in this case, ComparingEnumsByName doesn't do anything since the property involved is a string. What you could do instead is to use an anonymous type as the expectation.

Enum not default to 0 when not defined

I have an enum type defined as follows:
public enum OperationTypeEnum : byte
{
/// <remarks/>
#__NONE = 0,
/// <remarks/>
Sale = 1,
/// <remarks/>
Auth = 2
}
In my code, I cast an integer like so:
var operationType = (OperationTypeEnum) anotherIntVariable;
When anotherIntVariable is something undefined (e.g. 5), I am hoping to get 0 or __NONE back (since 5 is not defined as one of the valid enum values, but I receive 5 instead.
What do I need to change to make undefined enum values to be 0?
Thanks!
The answer was given by #plast1k.
Here is a generic extension for your problem
public static class OperationTypeEnumExtensions
{
public static T ToEnum<T>(this byte val) where T : struct
{
if(Enum.IsDefined(typeof(T), val))
return (T) Enum.Parse(typeof(T), val.ToString());
return default(T);
}
}
usage
value.ToEnum<OperationTypeEnum>()
C# enums are effectively integers and there are no compile or run time checks that you are using a "valid" value from your defined enum set. See this answer for more information https://stackoverflow.com/a/6413841/1724034
If you get a numerical value and need to only get actual enum values, you can use Enum.TryParse
The example displays the following output:
Converted '0' to None.
Converted '2' to Green.
8 is not an underlying value of the Colors enumeration.
blue is not a member of the Colors enumeration.
Converted 'Blue' to Blue.
Yellow is not a member of the Colors enumeration.
using System;
[Flags] enum Colors { None=0, Red = 1, Green = 2, Blue = 4 };
public class Example
{
public static void Main()
{
string[] colorStrings = { "0", "2", "8", "blue", "Blue", "Yellow", "Red, Green" };
foreach (string colorString in colorStrings)
{
Colors colorValue;
if (Enum.TryParse(colorString, out colorValue))
if (Enum.IsDefined(typeof(Colors), colorValue) | colorValue.ToString().Contains(","))
Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
else
Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
else
Console.WriteLine("{0} is not a member of the Colors enumeration.", colorString);
}
}
}
The safest method is to create an extension method for your enum class that will compare the enum values and if none of them initialize to #__NONE
If you are certain there are only a limited amount of enum values:
public static class OperationTypeEnumExtensions
{
public static OperationTypeEnum ToOperationTypeEnum(this int val)
{
switch (val)
{
case (int) OperatinTypeEnum.Sale:
return OperationTypeEnum.Sale;
cast (int) OperationTypeEnum.Auth:
return OperationTypeenum.Auth;
default:
return OperationTypeEnum.#_none;
}
}
}
Usage:
int myInt = GetMyIntValue();
OperationTypeEnum myEnum = myInt.ToOperationTypeEnum();
#If your enum class is defined as below.
public enum CategoryEnum : int
{
Undefined = 0,
IT= 1,
HR= 2,
Sales= 3,
Finance=4
}
Now if you want to find Undefined enum if value doesnot match 1,2,3,4 then using the following Enum.IsDefine() function
Enum.IsDefined(typeof(CategoryEnum), request.CategoryId)
#returns true if id matches any enum values
#else returns false
Now for parsing the enum values as string
public enum Mode
{
UNDEFINED = 0,
APP = 1,
TEXT = 2,
}
var value = Enum.TryParse(request.Mode, true, out Mode mode);
#returns mode enum
#Now to get Corresponding value for id or vice-vera, have an extension method as below:
public static T AsEnum<T>(this string input) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
Enum.TryParse(input, ignoreCase: true, out T result);
return (T)result;
}
Then fetch it using AsEnum() function:
var status = searchText.AsEnum<StatusEnum>();

Enum as parameter: Get name and index

I have an enum like this:
public enum Global
{
txt_test = 123
}
Now I want to use a call like this:
var text = lib.Get(Global.txt_test);
Method:
public TextString Get(Enum enumeration)
{
string name = enumeration.ToString();
int index = ?; // (int)enumeration not working
...
}
How to get the index of an enum in this case?
Or am I doing it wrong at all?
Thank you.
Solution:
public TextString Get(Enum enumeration)
{
string name = enumeration.ToString();
int index = Convert.ToInt32(enumeration);
...
}
Enum are convertible to int for retrieving their values:
public TextString Get(Enum enumeration)
{
string name = enumeration.ToString();
int index = Convert.ToInt32(enumeration);
// ...
return null;
}
Note that this will work because your enumeration is type of int by default. Enums can still be other value type like long :
enum Range : long { Max = 2147483648L, Min = 255L };
In this case, the conversion will lost precision.
If you only need the enum value (what you are calling "index") as a string, the best way is to use custom format strings as documented here: http://msdn.microsoft.com/en-us/library/c3s1ez6e%28v=vs.110%29.aspx
For example:
public TextString Get(Enum enumeration)
{
string index = enumeration.ToString("D");
// ...
return null;
}

Parsing string as enum

Consider the enum below:
public enum TestType
{
Mil,
IEEE
}
How can I parse the folowing strings to the above enum?
Military 888d Test in case of TestType.Mil
Or
IEEE 1394 in case of TestType.IEEE
My idea was to check if the first letters of string matches 'Mil' or 'IEEE' then I would set it as the enum I want, but the problemis there are other cases that should not be parsed!
Already answred by me : How to set string in Enum C#?
Enum cannot be string but you can attach attribute and than you can read the value of enum as below....................
public enum TestType
{
[Description("Military 888d Test")]
Mil,
[Description("IEEE 1394")]
IEEE
}
public static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return value.ToString();
}
here is good article if you want to go through it : Associating Strings with enums in C#
My understanding of your situation is that the string can come in any format. You could have strings like "Military 888d Test", "Mil 1234 Test", "Milit xyz SOmething"...
In such a scenario, a simple Enum.Parse is NOT going to help. You will need to decide for each value of the Enum, which combinations do you want to allow. Consider the code below...
public enum TestType
{
Unknown,
Mil,
IEEE
}
class TestEnumParseRule
{
public string[] AllowedPatterns { get; set; }
public TestType Result { get; set; }
}
private static TestType GetEnumType(string test, List<TestEnumParseRule> rules)
{
var result = TestType.Unknown;
var any = rules.FirstOrDefault((x => x.AllowedPatterns.Any(y => System.Text.RegularExpressions.Regex.IsMatch(test, y))));
if (any != null)
result = any.Result;
return result;
}
var objects = new List<TestEnumParseRule>
{
new TestEnumParseRule() {AllowedPatterns = new[] {"^Military \\d{3}\\w{1} [Test|Test2]+$"}, Result = TestType.Mil},
new TestEnumParseRule() {AllowedPatterns = new[] {"^IEEE \\d{3}\\w{1} [Test|Test2]+$"}, Result = TestType.IEEE}
};
var testString1 = "Military 888d Test";
var testString2 = "Miltiary 833d Spiral";
var result = GetEnumType(testString1, objects);
Console.WriteLine(result); // Mil
result = GetEnumType(testString2, objects);
Console.WriteLine(result); // Unknown
The important thing is populating that rules object with the relevant regular expressions or tests. How you get those values in to the array, really depends on you...
try this var result = Enum.Parse(type, value);
Please try this way
TestType testType;
Enum.TryParse<TestType>("IEEE", out testType);
and it you want to compare string then
bool result = testType.ToString() == "IEEE";
Simple method will do it for you:
public TestType GetTestType(string testTypeName)
{
switch(testTypeName)
{
case "Military 888d Test":
return TestType.Mil;
case "IEEE 1394":
return TestType.IEEE;
default:
throw new ArgumentException("testTypeName");
}
}
EDIT
use Enum.GetNames:
foreach (var value in Enum.GetNames(typeof(TestType)))
{
// compare strings here
if(yourString.Contains(value))
{
// what you want to do
...
}
}
If you using .NET4 or later you can use Enum.TryParse. and Enum.Parse is available for .NET2 and later.

string representation of an enum (estring)?

i need an enum or something similiar to do something like this:
public enum MyStringEnum {
[StringValue("Foo A")] Foo = "A",
[StringValue("Foo B")] Foo = "B" }
is this possible? my example, i return back a dataset with a value represented as either A,B,C,D,E .. i need a solution to return this as a string representation?
i guess the obvious would be to create an extension method or something which just had a switch statement in and return a string .. any other cleaner solutions?
regards,
dave
Here is something we use for our MVC applications to retrieve a display name for our enums. It uses a custom attribute and an extension method to retrieve the enum display name.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDisplayNameAttribute : Attribute
{
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public static string GetDisplayName(this Enum enumType)
{
var displayNameAttribute = enumType.GetType()
.GetField(enumType.ToString())
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.FirstOrDefault() as EnumDisplayNameAttribute;
return displayNameAttribute != null ? displayNameAttribute.DisplayName : Enum.GetName(enumType.GetType(), enumType);
}
Usage on the enum:
public enum Foo
{
[EnumDisplayName("Foo Bar")]
Bar = 0
}
Getting back the display name:
var f = Foo.Bar;
var name = f.GetDisplayName();
Would it be an option not to use enum and use structs instead?
struct FooEnum
{
private int value;
private string name;
private FooEnum(int value, string name)
{
this.name = name;
this.value = value;
}
public static readonly FooEnum A = new FooEnum(0, "Foo A");
public static readonly FooEnum B = new FooEnum(1, "Foo B");
public static readonly FooEnum C = new FooEnum(2, "Foo C");
public static readonly FooEnum D = new FooEnum(3, "Foo D");
public override string ToString()
{
return this.name;
}
//TODO explicit conversion to int etc.
}
You could then use FooEnum like an enum with an own ToString() overload:
FooEnum foo = FooEnum.A;
string s = foo.ToString(); //"Foo A"
If you want to do something like this:
MyStringEnum value = MyStringEnum.A;
string description = value.GetDescription();
// description == "Foo A"
Setup your enum like this:
public enum MyStringEnum
{
[Description("Foo A")]
A,
[Description("Foo B")]
B
}
And use a utility/extension method that reads the attribute:
public static string GetDescription(this MyStringEnum enumerationValue)
{
Type type = enumerationValue.GetType();
string name = enumerationValue.ToString();
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] member = type.GetMember(name);
if (member != null && member.Length > 0)
{
object[] attributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
return name;
}
I've seen this done where I would put
MyStringEnum.Foo.ToString();
In this case it would give "A"
The cleanest solution for this problem is to create a custom attribute that will store the string value you want for the enum constant. I've used that strategy in the past and it worked out fairly well. Here's a blog post detailing the work involved:
Enum With String Values In C# - Stefan Sedich's Blog
Of course this is only necessary if you need some kind of meaningful text. If the name of the enum constant works for you...then you can simply call ToString().

Categories

Resources