If I want to restrict the values of the spicelevel column in the database to 1, 2 and 3, I could do something like
private enum SpiceLevel
{
Low=1,
Medium=2,
Hot=3
}
Then in the code I could do (int)SpiceLevel.Low to pick 1 as the spice level.
Now what if I have a need where I can only accept "Red Rose","White Rose" and "Black Rose" for the values of a column in the database? What is a graceful way to handle this?
I am thinking of storing them in a config file or constants, but neither is as graceful as enums. Any ideas?
Update:
The answer here worked for me
You can use a property for this
public string[] AllowedRoses = new string[] { "Red Rose", "White Rose" ,"Black Rose" };
string _Rose = "Red Rose";
public string Rose
{
get
{
return _Rose;
}
set
{
if (!AllowedRoses.Any(x => x == value))
throw new ArgumentException("Not valid rose");
_Rose = value;
}
}
I can see the following options:
verify the value in the setter (see for example l4V's answer)
conceptually, you're thinking about an enum. So you could do the following:
enum RoseType { RedRose, WhiteRose, BlackRose };
and then provide appropriate conversion from this enum to string. Two convenient options how to do it are described here: Enum ToString with user friendly strings. One is to use a custom Description attribute, and the second (I'd prefer this one) to provide an extension method:
public static class RoseTypeExtensions
{
public static string GetString(this RoseType #this)
{
switch (#this)
{
case RoseType.RedRose:
return "Red Rose";
case RoseType.WhiteRose:
return "White Rose";
case RoseType.BlackRose:
return "Black Rose";
default:
throw new InvalidOperationException();
}
}
}
create a set of constants:
public class RoseType
{
public readonly RoseType RedRose = new RoseType("Red Rose");
public readonly RoseType WhiteRose = new RoseType("White Rose");
public readonly RoseType BlackRose = new RoseType("Black Rose");
public string Content { get; private set; }
private RoseType(string content)
{
this.Content = content;
}
public override string ToString()
{
return this.Content;
}
}
As Oskar Berggren correctly pointed out in the comment, RoseType should also provide other standard overrides beside ToString: Equals, GetHashCode, operator== and operator!=.
There is no really good solution. All of them require the database to be "synchronized" with the enum in C#.
Simplest solution:
What you said store the enum values as integers in the database.
Almost as simple but less efficient:
Store the values as strings in the database and convert between string and enum with anEnumVar.ToString() and Enum.Parse (or any of the other parse methods in Enum).
Complex but flexible:
Have a sort of enum in the database: a table with string values and ids and then use foreign keys to that table where you want to save the enums. This allows you to either select/update/insert using the numeric value or the string value (via a join).
It also maintains integrity as it is not possible to store an integer which has no corresponding enum value.
The downside is the complexity.
Create a mapping of string to enum with Dictionary<string, SpiceLevel> to associate the string to the Enum. Wrap them in a class.
You could also use a Decorator attribute [Name("Red Rose"] Low=1, and get that from the enum itself, but that involves reflection, which has some performance issues, especially when iterating through enum values to find the one with the matching attribute.
public static class Spice
{
public enum Level
{
Low = 1,
Medium = 2,
Hot = 3
}
private static readonly Dictionary<string, Level> spices = new Dictionary<string, Level>{
{ "Red Rose", Level.Low },
{ "White Rose", Level.Medium },
{ "Black Rose", Level.Hot },
};
public static bool TryGet(string spiceName, out Level spiceLevel) => spices.TryGetValue(spiceName, out spiceLevel);
public static string SpiceName(Level target) => Enum.GetName(typeof(Spice.Level), target);
}
/// <summary>
/// Some tests to validate it works. This could be a unit test or just in a console app
/// </summary>
public class SpiceTest
{
public void VerifyBlackRoseIsHot()
{
string subject = "Black Rose";
Spice.Level expectedSpice;
// Here's the ease of use. Pass a string, get an enum and whether it's a valid string
var result = Spice.TryGet(subject, out expectedSpice);
//Some Assertion from a unit test library
Assert.True(result, $"Unable to find spice '{subject}', when it should exist");
Assert.True(Spice.Level.Hot.Equals(expectedSpice), $"The returned spice '{ Spice.SpiceName(expectedSpice) }' was not the value 'Hot' as expected");
}
}
Related
I have enum:
enum MyEnum{
aaaVal1,
aaaVal2,
aaaVal3,
}
I need to have abbreviated version of 'MyEnum' which maps every item from 'MyEnum' to different values. My current approach is method which simply translates every item:
string translate(MyEnum myEnum)
{
string result = "";
switch ((int)myEnum)
{
0: result = "abc";
1: result = "dft";
default: result = "fsdfds"
}
return result;
}
the problem with this approach is that every time programmer changes MyEnum he should also change translate method.
This is not a good way of programming.
So..
Is there any more elegant solution for this problem?
Thank you :-)
Four options:
Decorate your enum values with attributes, e.g.
enum MyEnum
{
[Description("abc")]
AaaVal1,
[Description("dft")]
AaaVal2,
AaaVal3,
}
Then you can create a mapping (like the dictionary solution below) via reflection.
Keep the switch statement but switch on the enum value instead of a number for better readability:
switch (myEnum)
{
case MyEnum.AaaVal1: return "abc";
case MyEnum.AaaVal2: return "dft";
default: return "fsdfds";
}
Create a Dictionary<MyEnum, string>:
private static Dictionary<MyEnum, string> EnumDescriptions =
new Dictionary<MyEnum, string>
{
{ MyEnum.AaaVal1, "abc" },
{ MyEnum.AaaVal2, "dft" },
};
You'd need to handle the defaulting in the method, of course.
Use a resource file, with an entry for each string representation. This would be better if you're really trying to translate in a way that might need different translations for different cultures.
Considering that the use of descriptors on enums is quite common, here it's a good-enough class to do it:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
class EnumDescriptor : Attribute
{
public readonly string Description;
public EnumDescriptor(string description)
{
this.Description = description;
}
public static string GetFromValue<T>(T value) where T : struct
{
var type = typeof(T);
var memInfo = type.GetField(value.ToString());
var attributes = memInfo.GetCustomAttributes(typeof(EnumDescriptor), false);
if (attributes.Length == 0)
{
return null;
}
return ((EnumDescriptor)attributes[0]).Description;
}
}
enum MyEnum
{
[EnumDescriptor("Hello")]
aaaVal1,
aaaVal2,
aaaVal3,
}
string translate(MyEnum myEnum)
{
// The ?? operator returns the left value unless the lv is null,
// if it's null it returns the right value.
string result = EnumDescriptor.GetFromValue(myEnum) ?? "fsdfds";
return result;
}
I'm finding what you're trying to do a bit weird.
If you're making translations, then you should create a RESX file and create ACTUAL translations.
But to answer your question, I guess you could create another enum with the same amount of fields and same numbering (if you're using anything other than the default) and have that act as the abbreviated names. Connecting one to the other should be straightforward:
string GetAbbreviation(Enum1 enum1)
{
return ((Enum2)((int)enum1)).ToString();
}
Attributes will be nice solution for this case. You can specify translations for enumeration members via declarative way:
public class TranslateAttribute
{
public string Translation { get; private set; }
public TranslateAttribute(string translation)
{
Translation = translation;
}
}
enum MyEnum
{
[Translate("abc")]
aaaVal1,
[Translate("dft")]
aaaVal2,
[Translate("fsdfds")]
aaaVal3
}
After this you should write common method for obtaining translations. It should check attribute with translation (via reflection) and return translation if it was specified and default value in other cases.
I am writing a wrapper to a REST API. So, whenever I am retrieving items from the server, I just need to play around with the parameters (in the uri). The way I am doing it now works fine but I just feel there must be another elegance way to do this maybe with enum or something.
I don't like that I need to 'know' what are the options are as the Dictionary type is string. I tried with Dictionary<EnumType, string>, but I have more than one type of enum. Plus, I am not sure how to map the EnumType (key) to the appropriate value.
Basically, I am trying to avoid as much as possible the use of magic keyword.
Here is my partial code:
public string GetUnreadItems()
{
var options = new Dictionary<string, string>();
options.Add("ItemType", "Unread");
options.Add("SortBy", "Latest");
// GetItemsBasedOn(options);
}
public string GetAllItems()
{
var options = new Dictionary<string, string>();
options.Add("ItemType", "All");
// GetItemsBasedOn(options);
}
public string GetItemsBasedOn(Dictionary<string, string> options)
{
// Do request here based on options passed
// and return the result to caller function
}
EDIT:
This is what I am trying to implement http://getpocket.com/developer/docs/v3/retrieve
I would like to implement the options sort, detailType, contentType, Favorite, and State. And each of the options have their own options but only one can be selected at a time.
There are a few ways you could go about improving your current design. I don't agree that the solution I am about to present to you is the ideal solution, but given that you have already identified that you would like to use an enum I think you will be content with this solution.
What you can do is define an enum marked with the [Flags] attribute. Assign to each flag in the enum a value that is a power of two. If you want to combine options to create a single option use bitwise or just like I did with the flag named "All" in the proceeding sample:
[Flags]
public enum GetItemOptions
{
Read = 0x1,
Unread = 0x2,
All = 0x1 | 0x2,
SortByOldest = 0x4,
SortByLatest = 0x8
}
From your code sample, the first call will now look like this:
GetItemsBasedOn(GetItemOptions.Unread | GetItemOptions.SortByLatest);
And the second will look like this:
GetItemsBasedOn(GetItemOptions.All);
In order to enable this design you will need to adjust your GetItemsBasedOn method signature so that it specifies an argument of the GetItemOptions enum type. Below is an example of how you can handle different settings.
public static void GetItemsBasedOn(GetItemOptions getItemOption)
{
if (getItemOption.HasFlag(GetItemOptions.SortByOldest) && getItemOption.HasFlag(GetItemOptions.SortByLatest))
throw new ArgumentException("I can't sort by both...");
if (getItemOption.HasFlag(GetItemOptions.Read))
{
Console.WriteLine("READ");
}
if (getItemOption.HasFlag(GetItemOptions.Unread))
{
Console.WriteLine("UNREAD");
}
if (getItemOption.HasFlag(GetItemOptions.SortByOldest))
{
Console.WriteLine("SORT BY OLDEST");
}
else if (getItemOption.HasFlag(GetItemOptions.SortByLatest))
{
Console.WriteLine("SORT BY NLATEST");
}
}
I don't think you know much about bit-wise operations, and for that reason I simplified the code sample as much as possible by utilizing the Enum.HasFlag method which simply checks if the given GetItemOptions enum has a flag specified.
You may have bared witness to this pattern before when using RegexOptions Enumeration or ControlStyles Enumeration
Update
I would suggest that you create an enum for each parameter and define a class like this:
public class PocketDataRequest
{
public State? State { get; set; }
public Favourite? Favourite { get; set; }
public ContentType? ContentType { get; set; }
public Sort? Sort { get; set; }
public DetailType? DetailType { get; set; }
public Dictionary<string, string> ToPostData()
{
return GetType().GetProperties()
.Where(p => p.GetValue(this, null) != null)
.ToDictionary(p => p.Name,
p => p.GetValue(this, null).ToString());
}
}
This would leverage the following syntax:
PocketDataRequest pocketDataRequest = new PocketDataRequest();
pocketDataRequest.State = State.Unread;
pocketDataRequest.Sort = Sort.Newest;
GetItemsBasedOn(pocketDataRequest.ToPostData());
In my implementations ToPostData method, I use LINQ and Reflection, that is just because I am lazy. You need to manually evaluate each enum value, especially if you want to change the enum names to something more appropriate. Also, my code will fail if you try and pass the parameter titled favorite. This is because favorite takes either the number "0" or "1". This is not a big problem because what you can do it define the enum like this:
public enum Favourite
{
UnfavouritedItems = 0,
FavouritedItems = 1
}
and then simply cast the value (Int32) and add that value to the Dictionary<string, string> or NameValueCollection.
in java I could easily describe an enum with aditional data.
I could describe it something like this
public enum OperatorType
{
GreaterOrEqual (">=", "GreaterOrEqual"),
Greater (">" ,"Greater"),
Less ("<", "Less"),
LessOrEqual ("<=", "LessOrEqual"),
Equal ("==", "Equal"),
Between ("Between", "Between"),
Around ("Around","Around");
private final String symbol;
private final String name;
private OperatorType(final String symbol, final String name) {
this.symbol = symbol;
this.name = name;
}
}
And then add a static method that iterates over values(), adds all data to a hashmap and allow to retrieve from the map full enum data by one of its attriburtes as a key.
In brief, enum is a very developed type in java.
Now,
moving to c#, what are my options?
I want to hold an enum with its attributes, load it to a map, and retreive by key when I need. Do I have anything to assist (like, a singletone for each enum - which is not a good idea).
Thanks.
I would just create a class with public static readonly instances of each type and ditch enums altogether. You can use them as dictionary keys or do whatever you like. If you still intend to map them to an underlying data type (int) then you can create implicit operators for that too.
public class OperatorType
{
private static readonly Dictionary<int, OperatorType> OperatorMapping = new Dictionary<int, OperatorType>();
public static readonly OperatorType GreaterOrEqual = new OperatorType(0, ">=", "GreaterOrEqual");
public static readonly OperatorType Greater = new OperatorType(1, ">", "Greater");
public readonly String symbol;
public readonly String name;
private readonly int underlyingValue;
private OperatorType(int underlyingValue, string symbol, string name) {
this.underlyingValue = underlyingValue;
OperatorMapping[underlyingValue] = this;
this.symbol = symbol;
this.name = name;
}
public static implicit operator int(OperatorType operatorType)
{
return operatorType.underlyingValue;
}
public static implicit operator OperatorType(int value)
{
return OperatorMapping[value];
}
}
Sample usage:
Dictionary<OperatorType, string> operators = new Dictionary<OperatorType, string>();
operators.Add(OperatorType.GreaterOrEqual, "Greater or equal");
Console.WriteLine(operators[OperatorType.GreaterOrEqual]); //"Greater or equal"
OperatorType operatorType = 1;
Console.WriteLine(operatorType.name); //"Greater"
If you don't care about an underlying value, don't include it. Also consider whether or not the Dictionary mapping should be threadsafe for your usage. You can also expose a static IEnumerable<OperatorType> (or other collection) to get all operators defined if you want.
EDIT: On second thought, explicit operators are possibly preferable instead of implicit, both to conform with typical .NET best practices and to better match typical enum conversions.
The most convinient workaround might be to create an extension method to your enum type, and return the associated symbols.
Something like this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
tester t = tester.x;
t.testenums();
Console.ReadKey();
}
}
public static class ext
{
public static void testenums(this tester x)
{
Console.WriteLine(x.ToString());
}
}
public enum tester
{
x,
y
}
}
Of course you can write a more complex extension method, with return value, etc, this is just an example how to do it.
You can create an attribute:
public class EnumKeyAttribute : Attribute
{
public string Key { get; set; }
public string Description { get; set; }
public EnumKeyAttribute(string key, string description)
{
this.Key = key;
this.Description = description;
}
}
Then apply it to your enum
public enum OperatorType
{
[EnumKey(">=", "GreaterOrEqual")]
GreaterOrEqual,
[EnumKey(">", "Greater")]
Greater,
[EnumKey("<", "Less")]
Less,
[EnumKey("<=", "LessOrEqual")]
LessOrEqual,
[EnumKey("==", "Equal")]
Equal,
[EnumKey("Between", "Between")]
Between,
[EnumKey("Around", "Around")]
Around
}
To get the attribute data you can use reflection. Below is an example of getting the attribute for "Less"
MemberInfo memberInfo = typeof(OperatorType).GetMember(OperatorType.Less.ToString()).FirstOrDefault();
if(memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
Console.WriteLine(attribute.Key);
Console.WriteLine(attribute.Description);
}
But because these enums are not created at runtime you can increase your efficiency by creating a static method that looks up the value in a dictionary. Do this as an extension method for ease of use
public static class KeyFinder
{
private static Dictionary<OperatorType, EnumKeyAttribute> lookupTable =
new Dictionary<OperatorType, EnumKeyAttribute>();
public static EnumKeyAttribute GetKey(this OperatorType type)
{
if (lookupTable.ContainsKey(type))
{
return lookupTable[type];
}
MemberInfo memberInfo = typeof(OperatorType).GetMember(type.ToString()).FirstOrDefault();
if (memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
if (attribute != null)
{
lookupTable.Add(type, attribute);
return attribute;
}
}
// add a null value so next time it doesn't use reflection only to find nothing
lookupTable.Add(type, null);
return null;
}
}
So now to get the values you simply do the following:
OperatorType.Less.GetKey().Key
OperatorType.Less.GetKey().Description
Just be careful of null reference exceptions (since it will return null if it can't find an attribute). If you want to find by key you can simply create other extension methods that use the string value as the key.
C# doesn't really have the same feature. However there are several possibilities to get really close (and potentially more flexible as well).
Sticking to regular enums, you could use attributes to enrich with extra information. Of course, this requires reflection to work with that
public enum OperatorType
{
[DisplayName(">=")]
GreaterOrEqual,
// ...
}
There are several patterns to work with this, e.g. http://www.codeproject.com/Articles/28087/DisplayNameAttribute-for-Enumerations, google for more.
Another approach can be to enhance your enumeration types using regular classes:
public class OperatorType
{
public static OperatorType GreaterOrEqual = new OperatorType(">=", "GreaterOrEqual");
// ...
string symbol;
string name;
private OperatorType(string symbol, string name)
{
this.symbol = symbol;
this.name = name;
}
}
This article describes some other ways to work with enum-like types in C#
If you really need the functionality of Java-style enums in C#, I see three reasonable ways to implement it:
Use a C# enum and a static class of helper methods. You lose type safety, but this is an otherwise very workable solution.
Use a C# enum and a set of extension methods. Probably the most idiomatic C# solution, but you still have to deal with the loss of type safety (your extension methods should be able to cope with out-of-range values, even if only by throwing an exception).
Use the type-safe enum pattern that was common in Java before the language gained the enum keyword in Java 5. If you have non-trivial logic for each enum value, this would be my preference.
I need my enum to return a specific string, but I can't work out how to make it return a string with breaks in it without having a method to do the conversion. Is it possible to make LicenseTypes.DISCOUNT_EARLY_ADOPTER return DISCOUNT EARLY-ADOPTER without the helper method?
// All license types
public enum LicenseTypes
{
DISCOUNT,
DISCOUNT_EARLY_ADOPTER,
COMMERCIAL,
COMMERCIAL_EARLY_ADOPTER
}
// Convert enum to correct string
public static string LicenseTypeToString(LicenseTypes Enum)
{
if (Enum == LicenseTypes.COMMERCIAL)
return "COMMERCIAL";
else if (Enum == LicenseTypes.COMMERCIAL_EARLY_ADOPTER)
return "COMMERCIAL EARLY-ADOPTER";
else if (Enum == LicenseTypes.DISCOUNT)
return "DISCOUNT";
else if (Enum == LicenseTypes.DISCOUNT_EARLY_ADOPTER)
return "DISCOUNT EARLY-ADOPTER";
else
return "ERROR";
}
Firstly, a separate option from a helper method is simply to have a Dictionary<LicenseTypes, string> which you populate once. That would probably be the simplest approach, to be honest:
private static readonly Dictionary<LicenseTypes, string> LicenseDesciptions =
new Dictionary<LicenseTypes, string>
{
{ LicenseTypes.COMMERCIAL, "COMMERCIAL" },
{ LicenseTypes.COMMERCIAL_EARLY_ADOPTER, "COMMERCIAL EARLY-ADOPTER" },
{ LicenseTypes.DOMESTIC, "DOMESTIC" },
{ LicenseTypes.DOMESTIC_EARLY_ADOPTER, "DOMESTIC EARLY-ADOPTER" },
};
(As noted in comments, another alternative is a switch/case... but I personally prefer this way, as effectively you've got a data mapping, so it makes sense to use a data structure rather than an execution flow structure. It also means you can swap out dictionaries for different languages etc if you want.)
Secondly, one option would be to decorate each enum value with a [Description] attribute (or your own attribute if you want), and find that out with reflection - Unconstrained Melody has an extension method which can do that very easily:
// Throws ArgumentOutOfRangeException if the licenseType value isn't defined
// or doesn't have a description.
string description = licenseType.GetDescription();
Also, following .NET naming conventions it should be:
public enum LicenseType // Singular as it's not a Flags enum
{
Discount,
DiscountEarlyAdopter,
Commercial,
CommercialEarlyAdopter
}
A little reflection, and Attribute magic, and this should just answer it :)
Getting attributes of Enum's value
Might also make it an extension method.
here's how it should look (also added generics):
public static class MyExtensionsClass
{
public static string ToDescriptionString<T>(this T val)
where T : struct, IConvertible
{
if (typeof(T).IsEnum)
{
var type = val.GetType();
var memInfo = type.GetMember(val.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
return ((DescriptionAttribute)attributes[0]).Description;
}
return ""; //all paths must return a value
}
}
public enum LicenseTypes
{
[Description("DISCOUNT")]
DISCOUNT,
[Description("DISCOUNT EARLY-ADOPTER")]
DISCOUNT_EARLY_ADOPTER,
[Description("COMMERCIAL")]
COMMERCIAL,
[Description("COMMERCIAL EARLY-ADOPTER")]
COMMERCIAL_EARLY_ADOPTER
}
Thank you, guys that wrote these:
Enhance enums using extension methods
Create Generic method constraining T to an Enum
Good luck!
While it doesn't eliminate the helper method, note that in your case you could just special-case the values that you can't get using ToString:
switch (Enum) {
case LicenseTypes.COMMERCIAL_EARLY_ADOPTER:
return "COMMERCIAL EARLY-ADOPTER";
case LicenseTypes.DISCOUNT_EARLY_ADOPTER:
return "DISCOUNT EARLY-ADOPTER";
default
return Enum.ToString();
}
I use this from Google's dotnet client - StringValueAttribute.cs
and Utilities.cs
public enum LicenseType
{
[StringValue("DISCOUNT")] Discount,
[StringValue("DISCOUNT EARLY-ADOPTER")] DiscountEarlyAdopter,
[StringValue("COMMERCIAL")] Commercial,
[StringValue("COMMERCIAL EARLY-ADOPTER")] CommercialEarlyAdopter
}
Then you can simply do this:
licenseType.GetStringValue();
Convert to string using "G" format, then replace "_" (underscore) with spaces:
LicensceTypes license = LicenseTypes.COMMERCIAL_EARLY_ADOPTERS;
string licenseDescription = license.ToString("G").Replace('_', ' ');
// licenseDescription = "COMMERCIAL EARLY ADOPTERS"
I think I would use a class to avoid this scenario. :/
public class LicenceType
{
private string name;
public LicenceType(string Name)
{
this.name = Name;
}
public override string ToString()
{
return name;
}
}
public static class LicenceTypes
{
public static LicenceType DISCOUNT = new LicenceType("DISCOUNT");
public static LicenceType DISCOUNT_EARLY_ADOPTER= new LicenceType("DISCOUNT EARLY-ADOPTER");
public static LicenceType COMMERCIAL= new LicenceType("COMMERCIAL");
public static LicenceType COMMERCIAL_EARLY_ADOPTER= new LicenceType("COMMERCIAL EARLY-ADOPTER");
}
I want to set the space on my enum. Here is my code sample:
public enum category
{
goodBoy=1,
BadBoy
}
I want to set
public enum category
{
Good Boy=1,
Bad Boy
}
When I retrieve I want to see Good Boy result from the enum
You can decorate your Enum values with DataAnnotations, so the following is true:
using System.ComponentModel.DataAnnotations;
public enum Boys
{
[Display(Name="Good Boy")]
GoodBoy,
[Display(Name="Bad Boy")]
BadBoy
}
I'm not sure what UI Framework you're using for your controls, but ASP.NET MVC can read DataAnnotations when you type HTML.LabelFor in your Razor views.
Here' a Extension method
If you are not using Razor views or if you want to get the names in code:
public class EnumExtention
{
public Dictionary<int, string> ToDictionary(Enum myEnum)
{
var myEnumType = myEnum.GetType();
var names = myEnumType.GetFields()
.Where(m => m.GetCustomAttribute<DisplayAttribute>() != null)
.Select(e => e.GetCustomAttribute<DisplayAttribute>().Name);
var values = Enum.GetValues(myEnumType).Cast<int>();
return names.Zip(values, (n, v) => new KeyValuePair<int, string>(v, n))
.ToDictionary(kv => kv.Key, kv => kv.Value);
}
}
Then use it:
Boys.GoodBoy.ToDictionary()
You are misunderstanding what an enum is used for. An enum is for programming purposes, essentially giving a name to a number. This is for the programmer's benefit while reading the source code.
status = StatusLevel.CRITICAL; // this is a lot easier to read...
status = 5; // ...than this
Enums are not meant for display purposes and should not be shown to the end user. Like any other variable, enums cannot use spaces in the names.
To associate internal values with "pretty" labels you can display to a user, can use a dictionary or hash.
myDict["Bad Boy"] = "joe blow";
using System.ComponentModel;
then...
public enum category
{
[Description("Good Boy")]
goodboy,
[Description("Bad Boy")]
badboy
}
Solved!!
Think this might already be covered, some suggestions:
How do I have an enum bound combobox with custom string formatting for enum values?
C# Getting Enum values
Just can't beat stackoverflow ;) just sooo much on here nowdays.
Based on Smac's suggestion, I've added an extension method for ease, since I'm seeing a lot of people still having issues with this.
I've used the annotations and a helper extension method.
Enum definition:
internal enum TravelClass
{
[Description("Economy With Restrictions")]
EconomyWithRestrictions,
[Description("Economy Without Restrictions")]
EconomyWithoutRestrictions
}
Extension class definition:
internal static class Extensions
{
public static string ToDescription(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
}
Example using the enum:
var enumValue = TravelClass.EconomyWithRestrictions;
string stringValue = enumValue.ToDescription();
This will return Economy With Restrictions.
Hope this helps people out as a complete example. Once again, credit goes to Smac for this idea, I just completed it with the extension method.
That's not possible, an enumerator cannot contain white space in its name.
Developing on user14570's (nice) workaround referred above, here's a complete example:
public enum MyEnum
{
My_Word,
Another_One_With_More_Words,
One_More,
We_Are_Done_At_Last
}
internal class Program
{
private static void Main(string[] args)
{
IEnumerable<MyEnum> values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();
List<string> valuesWithSpaces = new List<string>(values.Select(v => v.ToString().Replace("_", " ")));
foreach (MyEnum enumElement in values)
Console.WriteLine($"Name: {enumElement}, Value: {(int)enumElement}");
Console.WriteLine();
foreach (string stringRepresentation in valuesWithSpaces)
Console.WriteLine(stringRepresentation);
}
}
Output:
Why don't you use ToString() ?
I mean that when use ToString(),it gives the enum value. Just you have to add some identifier to catch space.For example:
public enum category
{
good_Boy=1,
Bad_Boy
}
When you get an enum in codes like category a = ..., you can use ToString() method. It gives you value as a string. After that, you can simply change _ to empty string.
I used Regex to split the values by capital letter and then immediately join into a string with a space between each string in the returned array.
string.Join(" ", Regex.Split(v.ToString(), #"(?<!^)(?=[A-Z])"));
First get the values of the enum:
var values = Enum.GetValues(typeof(Category));
Then loop through the values and use the code above to get the values:
var ret = new Dictionary<int, string>();
foreach (Category v in values)
{
ret.Add((int)v, string.Join(" ", Regex.Split(v.ToString(), #"(?<!^)(?=[A-Z])")));
}
In my case I needed a dictionary with the value and display name so that it why I have the variable "ret"
C# now has a built in function to get the description from an enum. Here's how it works
My Enum:
using System.ComponentModel.DataAnnotations;
public enum Boys
{
[Description("Good Boy")]
GoodBoy = 1,
[Description("Bad Boy")]
BadBoy = 2
}
This is how to retrieve the description in code
var enumValue = Boys.GoodBoy;
string stringValue = enumValue.ToDescription();
Result is : Good Boy.
public enum MyEnum { With_Space, With_Two_Spaces } //I store spaces as underscore. Actual values are 'With Space' and 'With Two Spaces'
public MyEnum[] arrayEnum = (MyEnum[])Enum.GetValues(typeof(MyEnum));
string firstEnumValue = String.Concat(arrayEnum[0].ToString().Replace('_', ' ')) //I get 'With Space' as first value
string SecondEnumValue = String.Concat(arrayEnum[1].ToString().Replace('_', ' ')) //I get 'With Two Spaces' as second value
If you do not want to write manual annotations, you can use an extension method that will add spaces to the enum's names:
using System.Text.RegularExpressions;
public static partial class Extensions
{
public static string AddCamelSpace(this string str) => Regex.Replace(Regex.Replace(str,
#"([^_\p{Ll}])([^_\p{Ll}]\p{Ll})", "$1 $2"),
#"(\p{Ll})([^_\p{Ll}])" , "$1 $2");
public static string ToCamelString(this Enum e) =>
e.ToString().AddCamelSpace().Replace('_', ' ');
}
You can use like this:
enum StudentType
{
BCStudent,
OntarioStudent,
badStudent,
GoodStudent,
Medal_of_HonorStudent
}
StudentType.BCStudent.ToCamelString(); // BC Student
StudentType.OntarioStudent.ToCamelString(); // Ontario Student
StudentType.badStudent.ToCamelString(); // bad Student
StudentType.GoodStudent.ToCamelString(); // Good Student
StudentType.Medal_of_HonorStudent.ToCamelString(); // Medal of Honor Student
See on .NET fiddle
Retrieving enum value is pretty complicated to me, while enum value is different than its name. For this purpose, I would like to use a class with const fields and a list that contains all of these fields. Using this list, I could check later to validate.
public class Status
{
public const string NOT_STARTED = "not started";
public const string IN_PROGRESS = "in progress";
public const string ON_HOLD = "on hold";
public const string COMPLETED = "completed";
public const string REFUSED = "refused";
public static string[] List = new string[] {
NOT_STARTED,
IN_PROGRESS,
ON_HOLD,
COMPLETED,
REFUSED
};
}
class TestClass {
static void Main(string[] args) {
var newStatus = "new status"
if (!Status.List.Contains(newStatus))
{
// new status is not valid
}
if (newStatus == Status.IN_PROGRESS)
{
// new status in progress
}
}
}
I define Enum with underscore and replace when using later in code:
// Enum definition
public enum GroupName
{
Major_Features, Special_Features, Graphical_Features
};
// Use in code:
internal Group GetGroup(GroupName groupName)
{
//...
string name = groupName.ToString().Replace('_',' '));
//...
}
What is your purpose of this question, if you want to have a set of strings, then you want to have a integer value for each of keys, the best way is using a Dictionary from your keys and values, like this:
Dictionary<string, int> MyDictionary = new Dictionary<string, int>()
{
{"good Boy", 1 },
{"Bad Boy", 2 },
};
Then you can give the integer value from the key like this:
int value = MyDictionary["good Boy"];
You can write the spaced word in brackets. Then define a constructor to take up the values inside the bracket. As given below
public enum category
{
goodBoy("Good Boy"),
BadBoy("Bad Boy")
}
private String categoryType;
category(String categoryType) {
this.categoryType = categoryType;
}
You cannot have enum with spaces in .Net. This was possible with earlier versions of VB and C++ of course, but not any longer. I remember that in VB6 I used to enclose them in square brackets, but not in C#.
Since the original question was asking for adding a space within the enum value/name, I would say that the underscore character should be replaced with a space, not an empty string. However, the best solution is the one using annotations.
An enumerator cannot contain white space in its name.
As we know that enum is keyword used to declare enumeration.
you can check throw this link
https://msdn.microsoft.com/en-us/library/sbbt4032.aspx