Связывание дополнительной информации с .NET Enum - PullRequest
21 голосов
/ 25 марта 2009

Мой вопрос лучше всего иллюстрируется на примере.

Предположим, у меня есть перечисление:

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

Я хочу связать единичный вектор, соответствующий каждому направлению, с этим направлением. Например, я хочу что-то, что будет возвращать (0, 1) для Севера, (-1, 0) для Запада и т. Д. Я знаю, что в Java вы можете объявить метод внутри перечисления, который может обеспечить эту функциональность.

Мое текущее решение состоит в том, чтобы иметь статический метод - внутри класса, который определяет перечисление - который возвращает вектор, соответствующий переданному в ArrowDirection (метод использует HashTable для выполнения поиска, но это не очень важно). Это кажется ... нечистым.

Вопрос:
Есть ли передовое решение для хранения дополнительной информации, соответствующей перечислению в .NET?

Ответы [ 5 ]

37 голосов
/ 25 марта 2009

В C # 3.0 появился ФАНТАСТИЧЕСКИЙ новый способ сделать это. Ключ к этому прекрасному факту: у Enums могут быть методы расширения! Итак, вот что вы можете сделать:

public enum ArrowDirection
{
    North,
    South,
    East,
    West
}

public static class ArrowDirectionExtensions
{
     public static UnitVector UnitVector(this ArrowDirection self)
     {
         // Replace this with a dictionary or whatever you want ... you get the idea
         switch(self)
         {
             case ArrowDirection.North:
                 return new UnitVector(0, 1);
             case ArrowDirection.South:
                 return new UnitVector(0, -1);
             case ArrowDirection.East:
                 return new UnitVector(1, 0);
             case ArrowDirection.West:
                 return new UnitVector(-1, 0);
             default:
                 return null;
         }
     }
}

Теперь вы можете сделать это:

var unitVector = ArrowDirection.North.UnitVector();

Сладкое! Я узнал об этом только месяц назад, но это очень хорошее следствие новых функций C # 3.0.

Вот еще один пример в моем блоге.

3 голосов
/ 25 марта 2009

Я писал об этом здесь .

Попробуйте что-то подобное с Атрибутами .

  public enum Status {

    [Status(Description = "Not Available")]      

    Not_Available = 1,      

    [Status(Description = "Available For Game")] 

    Available_For_Game = 2,      

    [Status(Description = "Available For Discussion")] 

    Available_For_Discussion = 3,

  }

  public class StatusEnumInfo {

    private static StatusAttribute[] edesc; 

    public static String GetDescription(object e)

    {

      System.Reflection.FieldInfo f = e.GetType().GetField(e.ToString()); 

      StatusEnumInfo.edesc = f.GetCustomAttributes(typeof(StatusAttribute), false) as StatusAttribute[]; 

      if (StatusEnumInfo.edesc != null && StatusEnumInfo.edesc.Length == 1)         

        return StatusEnumInfo.edesc[0].Description; 

      else         

        return String.Empty;

    } 

    public static object GetEnumFromDesc(Type t, string desc)

    {

      Array x = Enum.GetValues(t); 

      foreach (object o in x) {

        if (GetDescription(o).Equals(desc)) {

          return o;

        }

      } return String.Empty;

    }

  }

  public class StatusAttribute : Attribute {

    public String Description { get; set; }

  }



  public class Implemenation {

    public void Run()

    {

      Status statusEnum = (Status)StatusEnumInfo.GetEnumFromDesc(typeof(Status), "Not Available"); 

      String statusString = StatusEnumInfo.GetDescription(Status.Available_For_Discussion);

    }

  }

Вместо Описание , используйте пользовательское свойство

1 голос
/ 25 марта 2009
using System.ComponentModel;
using System.Reflection;


public enum ArrowDirection
{

[Description("Northwards")]
North,

[Description("Southwards")]
South,

[Description("Eastwards")]
East,

[Description("Westwards")]
West
}

...

Создайте метод расширения для получения списка описаний:

public static class Enum<T> where T : struct
{

    /// <summary>
    /// Gets a collection of the enum value descriptions.
    /// </summary>
    /// <returns></returns>
    public static IList<string> GetDescriptions()
    {
        List<string> descriptions = new List<string>();
        foreach (object enumValue in Enum<T>.GetValues())
        {
            descriptions.Add(((Enum)enumValue).ToDescription());
        }
        return descriptions;

    }
}
0 голосов
/ 25 марта 2009

Мне кажется, что ваш метод статических методов довольно чист. Вы инкапсулируете enum и статический метод в одном классе. Изменения в перечислении централизованы в этом единственном классе.

Добавление метода в перечисление (согласно Java), кажется, добавляет сложности чему-то, что на самом деле является очень простой концепцией.

Подход, основанный на атрибутах, интересен, но опять-таки кажется, что он слишком сложен по сравнению со статическим методом.

0 голосов
/ 25 марта 2009

Одна вещь, на которую вы могли бы взглянуть, это шаблон «Type-Safe Enum». Это позволяет вам создать перечисление, которое на самом деле является полноценным статическим объектом, который может иметь методы / свойства / и т. Д.

http://www.javacamp.org/designPattern/enum.html

Джошуа Блох рассказывает об этом паттерне в своей книге «Эффективная Ява». Я использовал его во многих различных ситуациях, и на самом деле я предпочитаю его простым перечислениям. (Это не зависит от языка - он работает на Java, C # или почти на любом языке ОО).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...