Enumeration to boolean casting question - c#

I have the following enumeration:
public enum MyEnum
{
MyTrue,
MyFalse
}
And I'd like to eventually be able to automatically convert my enumeration to a boolean value, with a simple line like this:
MyEnum val = MyEnum.MyTrue;
bool IsThisTrue = val;
Currently, I have to do this:
bool IsThisTrue = val == MyEnum.MyTrue;
Is there some mechanism I can apply to my enumeration to allow for native enum->bool casting? I'm wondering if some variant of a typeconverter is what I need or not.
Thanks
Edit: There is a reason for my custom enumeration. Since this properties are all eventually bound to a property grid, we have mechanisms put in place to bind all of our custom enumerations to multi-lingual strings in resources files. We need all of the enum's we're using to be in a specific namespace, hence the "MyEnum" class.

That line would work only with an implicit static conversion operator (or maybe the more-confusing true() operator, but that is rarely seen in the wild). You cannot define operators on enums, so ultimately the answer is: no.
You could, however, write an extension method on MyEnum to return true or false.
static class MyEnumUtils {
public static bool Value(this MyEnum value) {
switch(value) {
case MyEnum.MyTrue: return true;
case MyEnum.MyFalse: return false;
default: throw new ArgumentOutOfRangeException("value");
// ^^^ yes, that is possible
}
}
}
then you can use bool IsThisTrue = val.Value();

Write an extension method like this:
public static bool ToBoolean(this MyEnum value) {
return value == MyEnum.MyTrue;
}
and forget about it

Try this:
public enum MyEnum
{
MyFalse = 0,
MyTrue = 1
}
then:
MyEnum val = MyEnum.MyTrue;
bool IsThisTrue = val;
bool IsThisTrue = Convert.ToBoolean((int)val);

Related

Check if flag contains any value of other flag

I would like compare two flags and see if they have any common value.
I'ld like having an extension method as weel in order to "speed up" coding (I'm going to use it often and on various Enum types). How can I?
This code tell me:
operator '&' cannot be applied to operands of type enum and enum
public enum Tag
{
Value1 = 1,
Value2 = 2,
Value3 = 4,
Value4 = 8,
Value5 = 16
}
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (me & other) != 0;
}
}
public class Program
{
public static void Main()
{
Tag flag1 = Tag.Value1 | Tag.Value2 | Tag.Value3;
Tag flag2 = Tag.Value2 | Tag.Value3 | Tag.Value4;
Console.WriteLine(flag1.HasAny(flag2)); // it should returns true. flag1.HasFlag(flag2) returns false.
}
}
I tried this as well:
return (((int)me) & ((int)other)) != 0;
but it raises the error:
Cannot convert type 'System.Enum' to 'int'
As per this answer (How to convert from System.Enum to base integer?)
You will need to wrap this code with an exception handler or otherwise ensure that both enums hold an integer.
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (Convert.ToInt32(me) & Convert.ToInt32(other)) != 0;
}
}
If you want a very generic HasAny extension for enums you could do the following. I've tested that this works with all the different underlying types that an enum can be. Also, if you are checking for flags you should probably have the [Flags] attribute decorating your enum, so this checks that the enums being checked have that attribute.
public static class FlagExtensions
{
public static bool HasAny(this Enum enumLeft, Enum enumRight)
{
if (enumLeft.GetType() != enumRight.GetType())
throw new ArgumentException("enum types should be the same");
if (!enumLeft.GetType().IsDefined(typeof(FlagsAttribute), inherit: false))
throw new ArgumentException("enum type should have the flags attribute");
dynamic enumLeftValue = Convert.ChangeType(enumLeft, enumLeft.GetTypeCode());
dynamic enumRightValue = Convert.ChangeType(enumRight, enumRight.GetTypeCode());
return (enumLeftValue & enumRightValue) != 0;
}
}
I tried this as well:
return (((int)me) & ((int)other)) != 0;
but it raises the error:
Cannot convert type 'System.Enum' to 'int'
Enums always implement IConvertible and IConvertible has 'ToInt32'. So you could write it like this:
public static class FlagExt
{
public static bool HasAny<TEnum>(this TEnum me, TEnum other)
where TEnum : Enum, IConvertible
{
return (me.ToInt32(null) & other.ToInt32(null)) != 0;
}
}

Are mutiple methods recommended when returning different types?

I'm returning values from an Entity object. Some of them are String typed and some are not. Right now, I did a quick solution as follows.
private String GetStringValue(Entity entity, String attribute, String substitute = "")
{
if(entity.Contains(attribute)
return entity[attribute] as String;
return substitute;
}
private String GetIntValue(Entity entity, String attribute, int substitute = 0)
{
if(entity.Contains(attribute)
return entity[attribute] as int;
return substitute;
}
Then I remembered that there's a syntax for generic typing (something like <TypeX>). My question is, however, if there's a point to start changing the existing code. I'll need to change the signature of the method in two places (return type and substitute type) but I fear that I'll need to do some complex coding inside the method as well.
On the other hand, I'd have a nice way to treat all the types possible (and I have a hunch we'll be working with more than strings and integers.
You will have to change the signature of the method in three places, because you also have to add the generic parameter:
private T GetValue<T>(Entity entity, String attribute, T substitute)
Within the method, there's no real need for any complex coding; replacing your current occurrences of string or int, respectively, with T, should suffice. (Note that the as operator can only be applied if you restrict T to reference types - which you probably don't want to do, because int is a value type).
Note that there are two issues with this method that you might consider drawbacks:
This generic method will support "all the types possible", but it will also support any types impossible (users are free to specify whatever type they like for T, and there is no way to restrict T while still supporting both string and int.
You cannot specify arbitrary default substitute values for each type. What you can do is declare a default value for substitute, namely default(T), but at least for string, that is not an empty string, but null.
You are right "something like" is the generic method. Check out generic methods there.
Next method looks good for your purpose.
private static T GetValue<T>(Entity entity, string attribute, T defaultValue)
{
if (!entity.Contains(attribute))
return defaultValue;
return (T)entity[attribute];
}
EDIT: updated according of the w0lf's comment.
If you don't want to change method signature, you can write a generic function and call it from all of these non generic versions.
private String GetStringValue(...){
return GetValue<String>(...);
}
By the way, you are looking for Generic methods
For e.g (from msdn)
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
...
Swap<int>(ref a, ref b);
or just
Swap(ref a, ref b); //type int is infered based on type of arguements and method signature
What class is Entity? Assuming it's a custom class, make it also generic, then this works:
private T Get<T>(Entity<T> entity, T attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
You can retrieve the value in this way:
var entity = new Entity<string>();
string val = Get<string>(entity, "attr", "subst");
You should define your Entity<T> class:
public class Entity<T>
{
// TODO: implement
public T this[string i] { get; set; }
// TODO: implement
internal bool Contains(string attribute)
{
return true;
}
// TODO: implement
// other properties and methods
}
And you may use a generic method:
private T GetStringValue<T>(Entity<T> entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute))
return entity[attribute];
return substitute;
}
If it is possible to generalize the code inside a method I would absolutely recommend to use it in a generic way. It makes the class smaller, better readable and you just have to change one method if requirements change. Your method looks like it can be made generic easily.
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if(entity.Contains(attribute))
return (T)entity[attribute];
return substitute;
}
If there would be some more logic to execute you could also use a dictionary with functions for the different types:
private IDictionary<Type, Func<Entity, string, object>> actions;
private void InitActions()
{
actions = new Dictionary<Type, Func<Entity, string, object>>
{
{
typeof (string), (entity, attribute) =>
{
// this could be your custom code for string
return entity[attribute];
}
},
{
typeof (int), (entity, attribute) =>
{
// this could be your custom code for int
return entity[attribute];
}
}
};
}
private T GetIntValue<T>(Entity entity, String attribute, T substitute = default(T))
{
if (entity.Contains(attribute) && actions.ContainsKey(typeof (T)))
{
Func<Entity, string, object> action = actions[typeof (T)];
return (T)action(entity, attribute);
}
return substitute;
}

C# enum contains value

I have an enum
enum myEnum2 { ab, st, top, under, below}
I would like to write a function to test if a given value is included in myEnum
something like that:
private bool EnumContainValue(Enum myEnum, string myValue)
{
return Enum.GetValues(typeof(myEnum))
.ToString().ToUpper().Contains(myValue.ToUpper());
}
But it doesn't work because myEnum parameter is not recognized.
Why not use
Enum.IsDefined(typeof(myEnum), value);
BTW it's nice to create generic Enum<T> class, which wraps around calls to Enum (actually I wonder why something like this was not added to Framework 2.0 or later):
public static class Enum<T>
{
public static bool IsDefined(string name)
{
return Enum.IsDefined(typeof(T), name);
}
public static bool IsDefined(T value)
{
return Enum.IsDefined(typeof(T), value);
}
public static IEnumerable<T> GetValues()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
// etc
}
This allows to avoid all this typeof stuff and use strongly-typed values:
Enum<StringSplitOptions>.IsDefined("None")
No need to write your own:
// Summary:
// Returns an indication whether a constant with a specified value exists in
// a specified enumeration.
//
// Parameters:
// enumType:
// An enumeration type.
//
// value:
// The value or name of a constant in enumType.
//
// Returns:
// true if a constant in enumType has a value equal to value; otherwise, false.
public static bool IsDefined(Type enumType, object value);
Example:
if (System.Enum.IsDefined(MyEnumType, MyValue))
{
// Do something
}
just use this method
Enum.IsDefined Method - Returns an indication whether a constant with a specified value exists in a specified enumeration
Example
enum myEnum2 { ab, st, top, under, below};
myEnum2 value = myEnum2.ab;
Console.WriteLine("{0:D} Exists: {1}",
value, myEnum2.IsDefined(typeof(myEnum2), value));
What you're doing with ToString() in this case is to:
Enum.GetValues(typeof(myEnum)).ToString()... instead you should write:
Enum.GetValues(typeof(myEnum).ToString()...
The difference is in the parentheses...
Also can use this:
enum myEnum2 { ab, st, top, under, below }
static void Main(string[] args)
{
myEnum2 r;
string name = "ab";
bool result = Enum.TryParse(name, out r);
}
The result will contain whether the value is contained in enum or not.
public static T ConvertToEnum<T>(this string value)
{
if (typeof(T).BaseType != typeof(Enum))
{
throw new InvalidCastException("The specified object is not an enum.");
}
if (Enum.IsDefined(typeof(T), value.ToUpper()) == false)
{
throw new InvalidCastException("The parameter value doesn't exist in the specified enum.");
}
return (T)Enum.Parse(typeof(T), value.ToUpper());
}
If your question is like "I have an enum type, enum MyEnum { OneEnumMember, OtherEnumMember }, and I'd like to have a function which tells whether this enum type contains a member with a specific name, then what you're looking for is the System.Enum.IsDefined method:
Enum.IsDefined(typeof(MyEnum), MyEnum.OneEnumMember); //returns true
Enum.IsDefined(typeof(MyEnum), "OtherEnumMember"); //returns true
Enum.IsDefined(typeof(MyEnum), "SomethingDifferent"); //returns false
If your question is like "I have an instance of an enum type, which has Flags attribute, and I'd like to have a function which tells whether this instance contains a specific enum value, then the function looks something like this:
public static bool ContainsValue<TEnum>(this TEnum e, TEnum val) where Enum: struct, IComparable, IFormattable, IConvertible
{
if (!e.GetType().IsEnum)
throw new ArgumentException("The type TEnum must be an enum type.", nameof(TEnum));
dynamic val1 = e, val2 = val;
return (val1 | val2) == val1;
}
Hope I could help.
Use the correct name of the enum (myEnum2).
Also, if you're testing against a string value you may want to use GetNames instead of GetValues.
just cast the enum as:
string something = (string)myEnum;
and now comparison is easy as you like
I think that you go wrong when using ToString().
Try making a Linq query
private bool EnumContainValue(Enum myEnum, string myValue)
{
var query = from enumVal in Enum.GetNames(typeof(GM)).ToList()
where enumVal == myValue
select enumVal;
return query.Count() == 1;
}

How to switch on enum that has repeated values or boolean values, in C#?

Given an enum type:
enum SOMEENUM
{
A = true,
B = false,
C = true
}
I want to switch on this like:
public void SWITCHON (SOMEENUM sn)
{
switch(s)
{
case SOMEENMUM.A : xxxxxxxx.......
}
}
But this doesn't compile; I guess it's using the bool value of the enum.
I want to do switch on Enum as if there is no value assigned to it.
First of all:
Enums in C# do not support bool as value.
So It should be integers.
If we set 2 property's of enum to the same value we can consider one of them lost.
From my understanding what you actually is trying to do is:
Somehow flag that 2 property's of enum are equal.
My suggestion:
public enum MyEnum
{
[Description("true")]
A = 1,
[Description("false")]
B = 2,
[Description("true")]
C = 3
}
Extension for Enum which will return bool
public static class EnumEx
{
public static bool GetDescriptionAsBool(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DescriptionAttribute attribute
= Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
as DescriptionAttribute;
if(attribute == null)
{
//throw new SomethingWentWrongException();
}
return bool.Parse(attribute.Description);
}
}
As a result you can switch normally and at any time can check what is your enums boll flag just calling GetDescriptionAsBool method of that instance.
Repeated values are just different names for the same thing. There's no way to tell the difference because enums are stored as the values, not as the names.
As for bool values, you use an if for those instead of a switch.
enums require numerical values but do not have to be set. I suggest just removing leaving it like
enum SOMEENUM
{
A,
B,
C
}
so
public void SWITCHON (SOMEENUM s)
{
switch(s)
{
case SOMEENMUM.A : ...do stuff...
break;
case SOMEENMUM.B : ...do stuff...
break;
case SOMEENMUM.c : ...do stuff...
break;
}
}

Cast a String to an Enum Tag in C# [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I Convert a string to an enum in C#?
How to Convert (to Cast) a string ( a text) to be Enum tag value in C#
You can do this:
MyEnum oMyEnum = (MyEnum) Enum.Parse(typeof(MyEnum), "stringValue");
While all the Enum.Parse people are correct, there's now Enum.TryParse!
Which improves things greatly.
I usually use generic Enum class for this stuff:
public static class Enum<T>
{
public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value);
}
public static List<T> GetValues()
{
List<T> values = new List<T>();
foreach (T value in Enum.GetValues(typeof(T)))
values.Add(value);
return values;
}
public static string GetName(object value)
{
return Enum.GetName(typeof(T), value);
}
// etc
// you also can add here TryParse
}
Usage is more simple:
Enum<DayOfWeek>.Parse("Friday");
Use Enum.Parse:
(EnumType)Enum.Parse(typeof(EnumType), "EnumString");
Or wrap it in a method like this:
T ParseEnum<T>(string stringValue)
{
return (T) Enum.Parse(typeof(T), stringValue);
}
.net provides some static methods on the System.Enum type to do this, and aside from the code that actually does the cast, there are several things to consider:
You have to know the enum type which contains the value you will cast TO.
It would be prudent to consider the fact that the string value you are attempting to cast might not be defined on your target enum type.
So if you have an enum:
public enum TestEnum
{
FirstValue,
SecondValue
}
Then the following 2 static methods are provided by the System.Enum class to cast a string value to an enum type:
Enum.IsDefined (.net 1.1 - 4 + silverlight) (usage)
TestEnum testEnum;
if( Enum.IsDefined(typeof(TestEnum), "FirstValue") )
{
testEnum = (TestEnum)Enum.Parse(typeof(TestEnum), "FirstValue");
}
Enum.TryParse ( .net 4 + silverlight) (usage)
TestEnum testEnum;
bool success = Enum.TryParse("FirstValue", out testEnum);
Alternatively, the Enum.Parse method (as mentioned by others) is provided if you do not need to perform any safety-checking. However, if you attempt to do something like this in our example,
Enum.Parse(TestEnum, "ThisValueDoesNotExist")
then .net will throw a System.ArgumentException which you have to handle.
So in short, while the syntax to do what you ask is simple, there are a few precautions I would recommend considering to ensure error-free code, especially if you are parsing strings obtained from user input. If the string is from a settings file or some other sort of value you can be sure is defined in your enum type, then it may be ok to skip some of the extra steps I have outlined in my answer.
I hope this helps!

Categories