Расширение перечислений в C # - PullRequest
13 голосов
/ 24 марта 2011

в java im используется для расширения значений перечисления или переопределения методов, подобных этому:

    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;
        }

    }

есть ли способ сделать что-то подобное в c # или перечисления более ограничены в c #

Ответы [ 4 ]

29 голосов
/ 24 марта 2011

Хотелось бы, чтобы перечисления были более мощными в .Net.И я люблю .Net!Вы можете использовать атрибуты для достижения того же.Напишите приведенный ниже код один раз и используйте его везде.Это будет длинный ответ, но я думаю, что это довольно хорошее решение, поэтому наберитесь терпения!

Использование

SomeEnum e = SomeEnum.ValueTwo;
string description = e.GetDescription();

Enum

Используйте атрибуты для описания перечисления, и этоценности.

[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

Атрибут, обеспечивающий правильную настройку перечисления.

/// <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;
    }
}

Получение описания

/// <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();
    }
}
17 голосов
/ 24 марта 2011

Перечисления в C # предназначены только для (целых) значений; они не могут иметь специальных методов или конструкторов, как в Java.

Однако вы можете определить методы расширения, которые работают с перечислениями для достижения почти того же эффекта:

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;
        }
    }
}

Тогда вы могли бы сказать:

var val = MyEnum.Foo;
var widget = val.ToWidget();
2 голосов
/ 24 марта 2011

перечисления в C # в основном просто именуются примитивами. Обычно они основаны на int, но могут основываться на любом числовом примитиве. Таким образом, C # не предлагает почти функциональность, которую делают перечисления Java. Компромисс в том, что перечисления C # намного легче, тогда как перечисления Java являются полноценными объектами.

public enum FooBar : int {
    Foo = 1,
    Bar = 2
}

Приведенное выше перечисление не сильно отличается от int, за исключением того, что теперь мы можем использовать FooBar.Foo вместо литерала 1. Вы можете приводить enum назад и вперед между int, и Enum имеет некоторые вспомогательные функции, которые могут помочь при работе с enum. Но это касается C #, они очень похожи на перечисления C или C ++.

0 голосов
/ 24 марта 2011

Вы можете сделать нечто подобное в C #, используя методы Extension.

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...