Map flaggable enum to array - c#

I have a flaggable enum from a database that I want to convert to an enum array of a 3rd party.
For that, I'm using the following code:
private TheirEnum[] GetTheirEnums(MyEnum? ourEnums)
{
List<TheirEnum> result = new List<TheirEnum>();
if (ourEnums != null)
{
if (ourEnums.Value.HasFlag(MyEnum.Geothermal))
{
result.Add(TheirEnum.GEOTHERMAL);
}
if (ourEnums.Value.HasFlag(MyEnum.SolarHeating))
{
result.Add(TheirEnum.SOLAR_HEATING);
}
}
else
{
result.Add(TheirEnum.NO_INFORMATION);
}
return result.ToArray();
}
However, as there are more than 50 entries in that enum list, I assume this would get very messy and ugly. Is there a better way to do this?

A simple solution would be to create OurEnum based on TheirEnum, then a simple cast would do the trick.
here is an example:
[Flags]
public enum TheirEnum
{
GEOTHERMAL=1,
SOLAR_HEATING=2,
NO_INFORMATION=4
}
[Flags]
public enum OurEnum
{
Geothermal=TheirEnum.GEOTHERMAL,
SolarHeating=TheirEnum.SOLAR_HEATING,
NoInformation=TheirEnum.NO_INFORMATION
}
or even you can just use the values:
[Flags]
public enum OurEnum
{
Geothermal=1,
SolarHeating=2,
NoInformation=4
}
then a simple cast would convert it:
var ourValue = OurEnum.Geothermal | OurEnum.NoInformation;
var theirValue = (TheirEnum) ourValue;
at last we can simply create an array based on flagged enums in theirValue :
var values=Enum.GetValues(typeof(TheirEnum));
var array= (from TheirEnum v in values where theirValue.HasFlag(v) select v).ToArray();

Related

How to return enum from property

Is there a way how to return full enum by property? Here is example of what I want to do:
// MyEnums.cs
public enum Languages
{
cs = 0,
pl = 1,
en = 2,
de = 3,
}
// General.cs
public static MyEnums.Languages Languages
{
get
{
return MyEnums.Languages;
}
}
enum is a type, i guess you actually want to get all enum-values. You could use this wrapper:
public static class EnumWrapper<T> where T : struct
{
public static T[] Values
{
get
{
Type ofT = typeof(T);
if (!ofT.IsEnum) throw new ArgumentException("Must be enum type");
return Enum.GetValues(ofT).Cast<T>().ToArray();
}
}
}
// ...
Languages[] languages = EnumWrapper<Languages>.Values;
If you want to return all available values defined in the enum, you can use
Enum.GetValues(typeof(MyEnums.Languages));
and modify your method so it returns a MyEnums.Languages[] (or a List<MyEnums.Languages>, which is always easier to manage for calling code)
To get all values in the enum, use Enum.GetValues. You might also want to cast it back to the correct type:
Languages[] languages = Enum.GetValues(typeof(Languages)).Cast<Languages>().ToArray();
// languages is an array containing { Languages.cs, Languages.pl, Languages.en, Languages.de }

enum backward compatibility

I have enum A which became two enums in version 2 enum B and C.
There is a function GetSpecificEnum() which returns enum A for version 1 and should return enum B and C for version 2 and above. Function itself doing some calculations and returns enum which meets my scenario.
My problem is to properly define this function which can return two versions.
I can always create two functions and somehow get calculations as private refactored method but i'm trying to avoid this.
Is there a way to do it ?
public ?? GetSpecificEnum()
{
if(version == 1)
{
//do some stuff
return A.SomeValue;
}
else
{
// do some stuff
return KeyValuePair<B, C>(B.SomeValue, C.SomeValue);
}
}
You can use the system type Enum as the return value for GetSpecificEnum. Your code will then have to check the type for the return, and handle it accordingly.
public enum A
{
ONE,TWO
};
public enum B
{
THREE,
FOUR
};
public Enum GetThing(int version)
{
return version == 1 ? (Enum)A.ONE : B.THREE;
}
public void DoThing()
{
Enum e = GetThing(1);
if (e is A)
{
// handle A
A _a = (A)e;
}
else
{
// handle B
}
}
You could do something like this if you are an API/product provider:
public enum OldEnum
{
One,
Two,
Three
}
public enum NewPart1
{
One,
Two
}
public enum NewPart2
{
Three
}
[Obsolete("This method is intended to by used be previous versions")]
public OldEnum GetEnum(someparameters here)
{
// Some processing here
return OldEnum.One;
}
public NewPart1 GetEnum(someparameters here)
{
// Do something here
return NewPart1.One;
}
public NewPart2 GetEnum(someparameters here)
{
// Do something here
return NewPart2.Three;
}
If your enumerations are split of old enumeration, you do not really need to make change to code. In the end, we are dealing with integers. Please note, split enumerations still retain same integer values as earlier. You can then just cast the integer value and send it across.

Enum item mapped to another value

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.

Enum values in a list

I've a enum class like,
public enum USERTYPE
{
Permanant=1,
Temporary=2,
}
in my business object I just declare this enum as
private List<USERTYPE> userType=new List<USERTYPE>;
and in the get/set method, I tried like
public List<USERTYPE> UserType
{
get
{
return userType;
}
set
{
userType= value;
}
}
here it returns the no of rows as 0, how can I get all the values in the Enum here, can anyone help me here...
You can use this to get all individual enum values:
private List<USERTYPE> userTypes = Enum.GetValues(typeof(USERTYPE)).Cast<USERTYPE>().ToList();
If you do things like this more often, you could create a generic utility method for it:
public static T[] GetEnumValues<T>() where T : struct {
if (!typeof(T).IsEnum) {
throw new ArgumentException("GetValues<T> can only be called for types derived from System.Enum", "T");
}
return (T[])Enum.GetValues(typeof(T));
}
GetValues returns System.Array, but we know it's really a TEnum[] (that is a one-dimensional array indexed from zero) where TEnum is USERTYPE in your case. Therefore use:
var allUsertypeValues = (USERTYPE[])Enum.GetValues(typeof(USERTYPE));
UserTypeCan you please try with that,
UserType = Enum.GetValues(typeof(USERTYPE)).OfType<USERTYPE>().ToList();
If you want to get specific enum value from the list user.UserType then you first need to Add enum value to this list:
var user = new User();
//1 value - PERMANENT
user.UserType.Add(USERTYPE.Permanent);
But if you only need to get all the possible values from an arbitrary enum then you can try Enum.GetValues
//2 values - Permanant and Temporary
var enums = Enum.GetValues(typeof(USERTYPE));
What you have is basically List of enum. Not individual items inside that enum.
To get list of enum values you can do
string[] str = Enum.GetNames(typeof(USERTYPE));
To use in get/set return string[] instead of List<>
public string[] UserType
{
get
{
return Enum.GetNames(typeof(USERTYPE));
}
}
I think set will not work here because you cannot add values in enum at runtime.

Numeric constants in enum (c#)

I'm creating this selectbox in a SharePoint web part and need to have a drop down with the current version so I need to use an Enum.
public enum SelectVersionEnum { 2010, 2007 };
Well you can see where it breaks, is there any way to use integers in a enum?
Most of all I'd like to use
public enum SelectVersionEnum { 2010=14, 2007=12 };
No, you can not name enums with integer names.
An enum value name is a normal identifier and must follow the same rules as everything else.
You can, however, use:
public enum SelectVersionEnum
{
Version2007 = 12,
Version2010 = 14
}
Additionally, Enum.Parse can parse strings with integers into their corresponding enum value, even if value described in the string doesn't exist.
Try the following in LINQPad:
void Main()
{
Enum.Parse(typeof(SelectVersionEnum), "12").Dump();
Enum.Parse(typeof(SelectVersionEnum), "14").Dump();
Enum.Parse(typeof(SelectVersionEnum), "2007").Dump();
}
public enum SelectVersionEnum
{
Version2007 = 12,
Version2010 = 14
}
The output:
Version2007
Version2010
2007
What do you think would've happened if you defined the following:
public enum SelectVersionEnum
{
12 = 14,
14 = 16
}
Does the string "14" now mean "12" or "14"?
Enum members must be valid C# identifiers.
They cannot start with numbers.
Instead, you can use something like Office2007, Office2010 or V2007, V2010.
No, enum identifiers can't start with a numeric character.
You can add an extension method to your enum like any other type.
So you could create an extension for your SelectVersionEnum to help you get the enum values in the right format...
public static class SelectVersionEnumExtension
{
public static int Version(this SelectVersionEnum enumValue)
{
return 0; // Obviously you should return something meaningful here..
}
}
This gives you a lot of flexibilty.
One way you could have numeric values associated with enums is by using the description attribute. For example you might have the enum:
[Serializable]
public enum SelectVersionEnum
{
[Description("2007")]
v2007,
[Description("2010")]
v2010
}
You could then write an extension method to get the numeric value you are looking for.
public static string Description(this Enum value)
{
var type = value.GetType();
var name = Enum.GetName(type, value);
if (name != null)
{
if (type.GetField(name) != null)
{
var attr = Attribute.GetCustomAttribute(type.GetField(name), typeof(DescriptionAttribute)) as DescriptionAttribute;
return attr != null ? attr.Description : name;
}
}
return null;
} // end
You would use it like this:
var version = SelectVersionEnum.v2007.Description();

Categories

Resources