I have enums like the following in my DB:
"Random Type", "Random Type1", "NewRandom"
Normally, I would represent the values in an enum like:
enum myTypes
{
Random Type = 0,...
}
but this is not possible, so I tried using a class
static class myTypes
{
public const string RandomType = "Random Type";
public const string NewRandom = "NewRandom";
}
This way, I can use the class like an Enum, but I'm wondering if this is the best implementation possible? Or is there away around creating Enums to allow space?
Thanks.
EDIT:
Please, I would also love to know whether there is anything wrong with my current implementation. I have a feeling my current implementation is better than most suggested solutions here.
Thanks
No, you can't do that. Enums are just typesafe ints.
There is a solution available, and I quite like it. Use the DescriptionAttribute.
You'd use it like this:
static enum myTypes
{
[Description("Random Type")]
RandomType,
[Descripton("New Random")]
NewRandom
}
and then you'd also need this extension method:
public static string GetDescription<T>(this T en) where T : struct, IConvertible
{
Type type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("The type is not an enum");
}
MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
return ((DescriptionAttribute)attrs[0]).Description;
}
}
return en.ToString();
}
And then with that, you could just do this:
myTypes.RandomType.GetDescription();
Enums are much similar to numbers (Integers specifically), rather than strings or so. Adhering to numbered Enums yields you to easy casting, flags-composition (e.g. AND, OR, etc).
I wouldn't use string constant in place of Enums, unless that will bring you more benefits than penalties.
If your goal is to describe to the user the Enum options, I'd suggest to consider to enrich each item with a Description attribute. It's a metadata, rather a real data, but it's also pretty easy to read using reflection.
Cheers
What I do is I define custom attribute [DisplayName(string)] that can be attached to enum values. You define your enum with display name on the values you wish were named with spaces / special characters:
public enum Test
{
None = 0,
[DisplayName("My Value")]
MyValue = 1,
[DisplayName("Spęćiał")]
Special = 2
}
Your implementation in addition to getting enum value name should also check if DisplayName attribute is set, and if so, it should take display name instead.
I would go with display name attributes:
[AttributeUsage(AttributeTargets.Field)]
public class EnumDisplayNameAttribute : DisplayNameAttribute
{
public EnumDisplayNameAttribute()
: base(string.Empty)
{
}
public EnumDisplayNameAttribute(string displayName)
: base(displayName)
{
}
}
public static class EnumExtensions
{
public static string ToDisplayName(this Enum enumValue)
{
var builder = new StringBuilder();
var fields = GetEnumFields(enumValue);
if (fields[0] != null)
for (int i = 0; i < fields.Length; i++)
{
var value = fields[i]
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.OfType<EnumDisplayNameAttribute>()
.FirstOrDefault();
builder.Append(value != null
? value.DisplayName
: enumValue.ToString());
if (i != fields.Length - 1)
builder.Append(", ");
}
return builder.ToString();
}
private static FieldInfo[] GetEnumFields(Enum enumValue)
{
var type = enumValue.GetType();
return enumValue
.ToString()
.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(type.GetField)
.ToArray();
}
}
usage for type:
public enum MyType
{
[DisplayName("Random Type")]
RandomType,
[DisplayName("New Random")]
NewRandom
}
would be:
var enumVariable = MyType.RandomType;
var stringRepresentation = enumVariable.ToDisplayName();
note that with that approach you would get ToString values if you omit attribute for some enum members.
You should probably not use strings as type indicators in your database. Use integers instead. If you like, you can have a "type table" in your database, where you can store the type names, instead of repeating them through the tables that uses them.
If you do this, then you can convert the integers from the database to enums as suggested above.
You can use Typesafe Enum pattern to achieve your goal.
Idea is to wrap your enum around a class. I guess this is what you want -
public class MyTypes
{
#region Enum Values
public static MyTypes RandomType = new MyTypes(0, "Random Type");
public static MyTypes NewRandom = new MyTypes(1, "New Random");
#endregion
#region Private members
private int id;
private string value;
private MyTypes(int id, string value)
{
this.id = id;
this.value = value;
}
#endregion
#region Overriden members
public override string ToString()
{
return value;
}
#endregion
public static List<MyTypes> GetValues()
{
return new List<MyTypes>() { MyTypes.RandomType, MyTypes.NewRandom };
}
}
Related
I want to replace the struct in the following code with a parent class with no data members and four subclasses, each subclass adds a different field. e.g. The SMValueFlt subclass adds a field named fltValue, and so on.
I am very new to C# and my Java is very rusty, so this is proving harder than I thought. And beyond actually setting up the class and subclasses i'm not sure how to proceed. Any help would be appreciated.
public class Interpreter {
enum TypeCode { None, IntType, FloatType, StringType };
struct SMValue {
public TypeCode t;
public int intValue;
public float fltValue;
public string strValue;
public SMValue( int i ) {
t = TypeCode.IntType; intValue = i; fltValue = 0.0F; strValue = null; }
public SMValue( float f ) {
t = TypeCode.FloatType; fltValue = f; intValue = 0; strValue = null; }
public SMValue( string s ) {
t = TypeCode.StringType; strValue = s; intValue = 0; fltValue = 0.0F; }
public override string ToString() {
if (t == TypeCode.IntType) return String.Format("{0}", intValue);
if (t == TypeCode.FloatType) return String.Format("{0}", fltValue);
if (t == TypeCode.StringType)
return strValue==null? "--null--" : strValue;
return "???";
}
}
}
I kept your TypeCode around in the first example, but it's not really necessary. You can inspect the type of a variable at runtime. For example,
var x = new SMFltValue() // (x.GetType() == typeof(SMFltValue)) = true, x is SMFltValue = true
Without using generics:
public enum TypeCode { IntType, FloatType, StringType };
public abstract class SMValue {
public TypeCode t;
public SMValue(TypeCode typeCode) {
t = typeCode;
}
public abstract string ToString();
}
public class SMFltValue : SMValue {
public float fltValue;
public SMFltValue(float f) : base(TypeCode.FloatType)
{
fltValue = f;
}
public override string ToString()
{
return String.Format("{0}", fltValue);
return String.Format("{0}", intValue);
return strValue==null ? "--null--" : strValue;
}
}
public class SMIntValue : SMValue {
public int intValue;
public SMIntValue(int i) : base(TypeCode.IntType)
{
intValue = i;
}
public override string ToString()
{
return String.Format("{0}", intValue);
}
}
public class SMStrValue : SMValue {
public string strValue;
public SMStrValue(string s) : base(TypeCode.StringType)
{
strValue = s;
}
public override string ToString()
{
return strValue==null ? "--null--" : strValue;
}
}
But generics would make it much nicer.
public class SMValue<T> {
public T value;
public SMValue(T value) {
this.value = value;
}
public string ToString() {
if (value == null)
{
return "--null--";
}
else
{
return string.Format("{0}", value);
}
}
}
Then you could use it as.
int i = 3;
float f = 5.0f;
string s = null;
new SMValue<int>(i).ToString() ==> 3
new SMValue<float>(f).ToString() ==> 5.0
new SMValue<string>(s).ToString() ==> "--null--"
The <int>, <float>, <string> aren't actually necessary because the compiler can infer the type from the variable being passed to the constructor.
The semantics of a struct with exposed fields are fundamentally different from those of a class. Fundamentally, each structure-type variable holds a bunch of fields stuck together with duct tape, while a class-type variable holds a not-necessarily-unique reference to a class object. If a structure type has two int fields, and one has two variables of that type, one has four integers which may be written independently. By contrast, if a class type has two int fields and one has two variables of that type, it's possible that the variables may at any given time reference different instances (in which case they would encapsulate a total of four independently-writable integers), or they may identify the same instance (in which case both variables would identify the same pair of integers, and so writing the first number in one pair would also write the first number in the other).
Some people think all types should behave like class objects, and regard as "evil" any types that don't. In reality, there are situations where it's useful to stick a bunch of variables together with duct tape (so they may be passed around as a unit when convenient), but guarantee that every bunch of variables is distinct. Class types can be used to mimic this behavior, awkwardly, but structures naturally work that way.
Without knowing exactly how you intend to use your type, it's hard to say whether a class will be able to fulfill your needs without having to rework all your client code. It's important to note, however, that any class used to replace a struct must almost always be immutable. If you can't easily convert your struct to a mutable class, you'll probably have to keep it a struct.
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.
If I have the following:
public enum TYPE
{
One = 1,
Two = 2,
Three = 3
}
When I do:
var a = TYPE.One;
I would like it to populate the variable a with a string in the format "01". In other words two digits with a leading zero.
Is it possible to do this by assigning some method to the SomeEnum? I realized I could use TYPE.One.ToString("00")but I would like to have it self-contained in the enum and something very simple to use.
You can add a string to each enum element using the description attribute.
e.g.
public Enum MyEnum
{
[Description("Value A Description")]
ValueA,
[Description[("Value B Description")]
ValueB
}
To retrieve the description value, use an extender class
public static class MyEnumExtender
{
public static string Description(this Enum Value)
{
FieldInfo FI = Value.GetType().GetField(Value.ToString());
IEnumerable<DescriptionAttribute> Attributes = FI.GetCustomAttributes(typeof(DescriptionAttribute), false).Cast<DescriptionAttribute>();
return (Attributes.Any()) ? Attributes.First().Description : Value.ToString();
}
}
....
MyEnum EnumVar = MyEnum.ValueA;
string Description = EnumVar.Description();
can do something like this :
public static class Ext {
public static string ToMyString(this Enumer en ) {
return ((int)en).ToString("00");
}
}
and after use this like:
public enum TYPE { One = 1, Two = 2, Three = 3 }
Type t = TYPE.One;
string s = t.ToMyString();
Yes, conceptually it's the same as like declaring a string , but it's hidden inside extension method.
Other solution is: to simply avoid, at this point, using enums in that way.
Don't use enums for that, but something like a Dictionary or Hash. Enums are there when there is a limited set of possibilities and you do not want or need a value. How it is stored is irrelevant.
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");
}
Is there a way of determining the name of a constant from a given value?
For example, given the following:
public const uint ERR_OK = 0x00000000;
How could one obtain "ERR_OK"?
I have been looking at refection but cant seem to find anything that helps me.
In general, you can't. There could be any number of constants with the same value. If you know the class which declared the constant, you could look for all public static fields and see if there are any with the value 0, but that's all. Then again, that might be good enough for you - is it? If so...
public string FindConstantName<T>(Type containingType, T value)
{
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
foreach (FieldInfo field in containingType.GetFields
(BindingFlags.Static | BindingFlags.Public))
{
if (field.FieldType == typeof(T) &&
comparer.Equals(value, (T) field.GetValue(null)))
{
return field.Name; // There could be others, of course...
}
}
return null; // Or throw an exception
}
I may be late.. but i think following could be the answer
public static class Names
{
public const string name1 = "Name 01";
public const string name2 = "Name 02";
public static string GetName(string code)
{
foreach (var field in typeof(Names).GetFields())
{
if ((string)field.GetValue(null) == code)
return field.Name.ToString();
}
return "";
}
}
and following will print "name1"
string result = Names.GetName("Name 01");
Console.WriteLine(result )
You may be interested in Enums instead, which can be programmatically converted from name to value and vice versa.
You won't be able to do this since constants are replaced at compilation time with their literal values.
In other words the compiler takes this:
class Foo
{
uint someField = ERR_OK;
}
and turns it into this:
class Foo
{
uint someField = 0;
}
I don't think you can do that in a deterministic way. What if there are multiple constants with the same value?
I suggest you use an enum to represent your constant.
Or
string ReturnConstant(uint val)
{
if(val == 0x00000000)
return "ERR_OK";
else
return null;
}
The easiest way would be to switch to using an enum