Enum Extentions

S

Shapper

Hello,

I have the following Enum:

public enum FruitsEnum {
[FruitColor("Red")]
Apple = 1,
[FruitColor("Green")]
Kiwi = 2,
[FruitColor("Yellow")]
Pear = 3
};

The FruitColor attribute is as follows:

public sealed class FruitColorAttribute : Attribute {
public String Color { get; set; }
public FruitColorAttribute(String color) {
this.Color = color;
}
}

I have two extensions (Name and Value):

public static class FruitEnumExtensions {
public static String Name(this FruitsEnum value) {
return Enum.IsDefined(typeof(FruitsEnum), value) ? Enum.GetName(typeof(FruitsEnum), value) : null;
}
public static Int32? Value(this FruitsEnum value) {
return Enum.IsDefined(typeof(FruitsEnum), value) ? (Int32?)value : new Nullable<Int32>();
}
}

But when I try to use it as follows:

String name = FruitsEnum.Apple.Name;
Int32? value = FruitsEnum.Apple.Value;

And I get the following errors:

Cannot convert method group 'Name' to non-delegate type 'string'. Did you intend to invoke the method?
Cannot convert method group 'Value' to non-delegate type 'int?'. Did you intend to invoke the method?

1 - What am I doing wrong?
2 - Is it possible to make the extensions generic and apply it to any Enum?
3 - How can I make an extension to get the value of an Attribute given its type?
Something like: myEnum.GetAttribute<FruitColorAttribute>();

Thank You,
Miguel
 
S

Shapper

Hello,



I have the following Enum:



public enum FruitsEnum {

[FruitColor("Red")]

Apple = 1,

[FruitColor("Green")]

Kiwi = 2,

[FruitColor("Yellow")]

Pear = 3

};



The FruitColor attribute is as follows:



public sealed class FruitColorAttribute : Attribute {

public String Color { get; set; }

public FruitColorAttribute(String color) {

this.Color = color;

}

}



I have two extensions (Name and Value):



public static class FruitEnumExtensions {

public static String Name(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? Enum.GetName(typeof(FruitsEnum), value) : null;

}

public static Int32? Value(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? (Int32?)value : new Nullable<Int32>();

}

}



But when I try to use it as follows:



String name = FruitsEnum.Apple.Name;

Int32? value = FruitsEnum.Apple.Value;



And I get the following errors:



Cannot convert method group 'Name' to non-delegate type 'string'. Did you intend to invoke the method?

Cannot convert method group 'Value' to non-delegate type 'int?'. Did you intend to invoke the method?



1 - What am I doing wrong?

2 - Is it possible to make the extensions generic and apply it to any Enum?

3 - How can I make an extension to get the value of an Attribute given its type?

Something like: myEnum.GetAttribute<FruitColorAttribute>();



Thank You,

Miguel

Name() instead of Name ... My Brain was probably turned off.

Anyway I came up with the following extensions:

public static class EnumExtensions {

public static String GetName<T>(this T value) {
return Enum.IsDefined(typeof(T), value) ? Enum.GetName(typeof(T), value) : null;
} // Name

public static Int32? GetValue<T>(this T value) {
return Enum.IsDefined(typeof(T), value) ? (Int32)(Object)value : new Nullable<Int32>();
} // Value

}


A few notes:

1 - When the value is not defined I am returning NULL.
For the Name (String) it does not change anything.
But for the Value it forces me to use nullable int.
I am not sure if this is the best option.

Enum.TryParse method returns 0 when invalid.
I does not make a lot of sense to me ...
The first enum value might start with 0 or 1.

2 - I had a few problems parsing T to Int32.
I used (Int32)(Object)value. Is there a better solution?

3 - I would like to get the value of an attribute:

FruitsEnum.Apple.GetAttributeValue<FruitColorAttribute>();

How can I do this?

Thank You,
Miguel
 
M

Marcel Müller

public static Int32? GetValue<T>(this T value) {
return Enum.IsDefined(typeof(T), value) ? (Int32)(Object)value : new Nullable<Int32>();
} // Value
2 - I had a few problems parsing T to Int32.
I used (Int32)(Object)value. Is there a better solution?

Well, dark chapter of the C# language.

You can't write
public static Int32? GetValue<T>(this T value)
where T : Enum // <-- not valid
{ return Enum.IsDefined(typeof(T), value) ? (Int32)value :
default(Int32?);
}
because enums do not really derive from Enum.

3 - I would like to get the value of an attribute:

FruitsEnum.Apple.GetAttributeValue<FruitColorAttribute>();

How can I do this?

First of all, you cannot get the /value/ of an attribute in a generic
way, because the definition of an Attribute class does not require
anything like a value at all. You can get the attribute itself by using
reflection.
Of course, different attribute classes could implement some common
interface to get the value. And if you restrict your GetAttributeValue
generic to this interface then can extract the value.

Unfortunately as in the example above you cannot restrict your extension
reasonably to enum types.


Marcel
 
S

Shapper

Hello,



I have the following Enum:



public enum FruitsEnum {

[FruitColor("Red")]

Apple = 1,

[FruitColor("Green")]

Kiwi = 2,

[FruitColor("Yellow")]

Pear = 3

};



The FruitColor attribute is as follows:



public sealed class FruitColorAttribute : Attribute {

public String Color { get; set; }

public FruitColorAttribute(String color) {

this.Color = color;

}

}



I have two extensions (Name and Value):



public static class FruitEnumExtensions {

public static String Name(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? Enum.GetName(typeof(FruitsEnum), value) : null;

}

public static Int32? Value(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? (Int32?)value : new Nullable<Int32>();

}

}



But when I try to use it as follows:



String name = FruitsEnum.Apple.Name;

Int32? value = FruitsEnum.Apple.Value;



And I get the following errors:



Cannot convert method group 'Name' to non-delegate type 'string'. Did you intend to invoke the method?

Cannot convert method group 'Value' to non-delegate type 'int?'. Did you intend to invoke the method?



1 - What am I doing wrong?

2 - Is it possible to make the extensions generic and apply it to any Enum?

3 - How can I make an extension to get the value of an Attribute given its type?

Something like: myEnum.GetAttribute<FruitColorAttribute>();



Thank You,

Miguel

Hello,

I ended up with the following extensions:

public static T GetAttribute<T>(this Enum value) where T : Attribute {

T attribute;

MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault();

if (info != null) {
attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault();
return attribute;
}
return null;

} // GetAttribute

public static String GetName(this Enum value) {

return Enum.IsDefined(value.GetType(), value) ? Enum.GetName(value.GetType(), value) : null;

} // GetName

public static Int32? GetValue(this Enum value) {

return Enum.IsDefined(value.GetType(), value) ? Convert.ToInt32(value) : new Nullable<Int32>();

} // GetValue

They seem to work. What do you think?

Thank You,
Miguel
 
S

Shapper

Hello,



I have the following Enum:



public enum FruitsEnum {

[FruitColor("Red")]

Apple = 1,

[FruitColor("Green")]

Kiwi = 2,

[FruitColor("Yellow")]

Pear = 3

};



The FruitColor attribute is as follows:



public sealed class FruitColorAttribute : Attribute {

public String Color { get; set; }

public FruitColorAttribute(String color) {

this.Color = color;

}

}



I have two extensions (Name and Value):



public static class FruitEnumExtensions {

public static String Name(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? Enum.GetName(typeof(FruitsEnum), value) : null;

}

public static Int32? Value(this FruitsEnum value) {

return Enum.IsDefined(typeof(FruitsEnum), value) ? (Int32?)value : new Nullable<Int32>();

}

}



But when I try to use it as follows:



String name = FruitsEnum.Apple.Name;

Int32? value = FruitsEnum.Apple.Value;



And I get the following errors:



Cannot convert method group 'Name' to non-delegate type 'string'. Did you intend to invoke the method?

Cannot convert method group 'Value' to non-delegate type 'int?'. Did you intend to invoke the method?



1 - What am I doing wrong?

2 - Is it possible to make the extensions generic and apply it to any Enum?

3 - How can I make an extension to get the value of an Attribute given its type?

Something like: myEnum.GetAttribute<FruitColorAttribute>();



Thank You,

Miguel

Or instead of:

public static T GetAttribute<T>(this Enum value) where T : Attribute {

T attribute;

MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault();

if (info != null) {
attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault();
return attribute;
}
return null;

} // GetAttribute

Something simpler as follows:

public static T GetAttribute<T>(this Enum value) where T : Attribute {
return value.GetType().GetTypeInfo()
.GetDeclaredField(value.ToString())
.GetCustomAttribute<T>();
}

Which one is better? Or even something else?

Thank You,
Miguel
 
M

Marcel Müller

Something simpler as follows:

public static T GetAttribute<T>(this Enum value) where T : Attribute {
return value.GetType().GetTypeInfo()
.GetDeclaredField(value.ToString())
.GetCustomAttribute<T>();
}

Which one is better? Or even something else?

The latter causes a NullReferenceException if value is a binary
combination of Enum values.


Marcel
 
A

Arne Vajhøj

Or instead of:

public static T GetAttribute<T>(this Enum value) where T : Attribute {

T attribute;

MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault();

if (info != null) {
attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault();
return attribute;
}
return null;

} // GetAttribute

Something simpler as follows:

public static T GetAttribute<T>(this Enum value) where T : Attribute {
return value.GetType().GetTypeInfo()
.GetDeclaredField(value.ToString())
.GetCustomAttribute<T>();
}

Which one is better? Or even something else?

Definitely something else.

You should use a class with a property instead of
this enum.

You can make the contructor private to limit the
instances.

public class Fruit
{
private int _value;
private string _color;
public int Value { get { return _value; } }
public string Color { get { return _color; } }
private Fruit(int val, string col)
{
_value = val;
_color = col;
}
public static Fruit Apple = new Fruit(1, "Red");
public static Fruit Kiwi = new Fruit(2, "Green");
public static Fruit Pear = new Fruit(3, "Yellow");
}

And add more methods as needed.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top