Extending enums in c#
in java im used to extending enum values or overriding methods like this :
enum SomeEnum
{
option1("sv")
{
public String toString()
{
return "Some value";
}
},
option2;
private String PassedValue;
public SomeEnum(String somevalue)
{
this.PassedValue = somevalue;
}
public SomeEnum()
{
this.PassedValue = "Default Value";
}
public String getPassedValue()
{开发者_开发百科
return this.PassedValue;
}
}
is there a way to do something similar in c# or are enums more limited in c#
I wish enums were more powerful in .Net. And I love .Net! You can use attributes to accomplish the same thing. Write the code below once and use it everywhere. This will be a long answer but I think it's a pretty good solution so have patience!
Usage
SomeEnum e = SomeEnum.ValueTwo;
string description = e.GetDescription();
The Enum
Use attributes to describe the enum and it's values.
[DescriptiveEnumEnforcement(DescriptiveEnumEnforcement.EnforcementTypeEnum.ThrowException)]
public enum SomeEnum
{
[Description("Value One")]
ValueOne,
[Description("Value Two")]
ValueTwo,
[Description("Value 3")]
ValueThree
}
DescriptionAttribute
/// <summary>Indicates that an enum value has a description.</summary>
[AttributeUsage(AttributeTargets.Field)]
public class DescriptionAttribute : System.Attribute
{
/// <summary>The description for the enum value.</summary>
public string Description { get; set; }
/// <summary>Constructs a new DescriptionAttribute.</summary>
public DescriptionAttribute() { }
/// <summary>Constructs a new DescriptionAttribute.</summary>
/// <param name="description">The initial value of the Description property.</param>
public DescriptionAttribute(string description)
{
this.Description = description;
}
/// <summary>Returns the Description property.</summary>
/// <returns>The Description property.</returns>
public override string ToString()
{
return this.Description;
}
}
DescriptiveEnumEnforcementAttribute
An attribute to ensure your enum's are properly configured.
/// <summary>Indicates whether or not an enum must have a NameAttribute and a DescriptionAttribute.</summary>
[AttributeUsage(AttributeTargets.Enum)]
public class DescriptiveEnumEnforcementAttribute : System.Attribute
{
/// <summary>Defines the different types of enforcement for DescriptiveEnums.</summary>
public enum EnforcementTypeEnum
{
/// <summary>Indicates that the enum must have a NameAttribute and a DescriptionAttribute.</summary>
ThrowException,
/// <summary>Indicates that the enum does not have a NameAttribute and a DescriptionAttribute, the value will be used instead.</summary>
DefaultToValue
}
/// <summary>The enforcement type for this DescriptiveEnumEnforcementAttribute.</summary>
public EnforcementTypeEnum EnforcementType { get; set; }
/// <summary>Constructs a new DescriptiveEnumEnforcementAttribute.</summary>
public DescriptiveEnumEnforcementAttribute()
{
this.EnforcementType = EnforcementTypeEnum.DefaultToValue;
}
/// <summary>Constructs a new DescriptiveEnumEnforcementAttribute.</summary>
/// <param name="enforcementType">The initial value of the EnforcementType property.</param>
public DescriptiveEnumEnforcementAttribute(EnforcementTypeEnum enforcementType)
{
this.EnforcementType = enforcementType;
}
}
Getting the Description
/// <summary>Provides functionality to enhance enumerations.</summary>
public static partial class EnumUtil
{
/// <summary>Returns the description of the specified enum.</summary>
/// <param name="value">The value of the enum for which to return the description.</param>
/// <returns>A description of the enum, or the enum name if no description exists.</returns>
public static string GetDescription(this Enum value)
{
return GetEnumDescription(value);
}
/// <summary>Returns the description of the specified enum.</summary>
/// <param name="value">The value of the enum for which to return the description.</param>
/// <returns>A description of the enum, or the enum name if no description exists.</returns>
public static string GetDescription<T>(object value)
{
return GetEnumDescription(value);
}
/// <summary>Returns the description of the specified enum.</summary>
/// <param name="value">The value of the enum for which to return the description.</param>
/// <returns>A description of the enum, or the enum name if no description exists.</returns>
public static string GetEnumDescription(object value)
{
if (value == null)
return null;
Type type = value.GetType();
//Make sure the object is an enum.
if (!type.IsEnum)
throw new ApplicationException("Value parameter must be an enum.");
FieldInfo fieldInfo = type.GetField(value.ToString());
object[] descriptionAttributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
//If no DescriptionAttribute exists for this enum value, check the DescriptiveEnumEnforcementAttribute and decide how to proceed.
if (descriptionAttributes == null || descriptionAttributes.Length == 0)
{
object[] enforcementAttributes = fieldInfo.GetCustomAttributes(typeof(DescriptiveEnumEnforcementAttribute), false);
//If a DescriptiveEnumEnforcementAttribute exists, either throw an exception or return the name of the enum instead.
if (enforcementAttributes != null && enforcementAttributes.Length == 1)
{
DescriptiveEnumEnforcementAttribute enforcementAttribute = (DescriptiveEnumEnforcementAttribute)enforcementAttributes[0];
if (enforcementAttribute.EnforcementType == DescriptiveEnumEnforcementAttribute.EnforcementTypeEnum.ThrowException)
throw new ApplicationException("No Description attributes exist in enforced enum of type '" + type.Name + "', value '" + value.ToString() + "'.");
return GetEnumName(value);
}
else //Just return the name of the enum.
return GetEnumName(value);
}
else if (descriptionAttributes.Length > 1)
throw new ApplicationException("Too many Description attributes exist in enum of type '" + type.Name + "', value '" + value.ToString() + "'.");
//Return the value of the DescriptionAttribute.
return descriptionAttributes[0].ToString();
}
}
Enums in C# are for (integer) values only; they cannot have special methods or constructors like in Java.
However, you can define extension methods that work on enums to achieve nearly the same effect:
public enum MyEnum {
Foo = 1,
Bar = 2,
Default = Foo
}
public static class MyEnumExtensions
{
public static Widget ToWidget(this MyEnum enumValue) {
switch (enumValue) {
case MyEnum.Foo:
return new Widget("Foo!");
case MyEnum.Bar:
return new Widget("Bar...");
default:
return null;
}
}
}
Then you could say:
var val = MyEnum.Foo;
var widget = val.ToWidget();
enums in C# are basically just named primitives. They typically are based on int
, but can be based on any numeric primitive. So C# does not offer nearly the functionality that Java enums do. The trade off is C# enums are much lighter, whereas Java enums are full fledged objects.
public enum FooBar : int {
Foo = 1,
Bar = 2
}
The above enum is not much different from an int
, except we can now use FooBar.Foo
instead of the literal 1
. You can cast the enum back and forth between ints, and Enum
has some helper functions that can help when working with enums. But that's about it for C#, they are much like C or C++ enums.
You can do something similar in C# using Extension methods.
enum Test
{
Value1,
Value2,
Value3
}
static class TextExtensions
{
public static string Value(this Test value)
{
string stringValue = default(String);
switch (value)
{
case Test.Value1:
{
stringValue = "some value 1";
} break;
case Test.Value2:
{
stringValue = "some value 2";
}; break;
case Test.Value3:
{
stringValue = "some value 3";
}; break;
}
return stringValue;
}
}
class Program
{
static void Main(string[] args)
{
Console.Write(Test.Value1.Value());
Console.ReadLine();
}
}
精彩评论