枚举除字符串以外的返回类型?

时间:2009-07-08 10:48:27

标签: c# enums

由于枚举使用整数,我可以使用哪种其他结构来对类链接的值进行类似枚举的访问:

[我知道这是错的,正在寻找替代方案]

private enum Project
    {
        Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"),
        Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2"),
        Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"),
        Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435"),
        Replacement = new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C"),
        Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F"),
        Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190"),
        Queries = new Guid("9985242-516A-4151-B7DD-851112F562")
    }

编辑2014-07-20

这是对这个问题的较新答案。将Attribute类与辅助方法一起使用,定义枚举所需的额外属性。

 public enum MultiValueEnum
    {
        [FooAttribute("alpha", 20d, true)]
        First,
        [FooAttribute("beta", 40.91d, false)]
        Second,
        [FooAttribute("gamma", 1.2d, false)]
        Third,
    }     

  public class FooAttribute : Attribute
            {
                internal FooAttribute(string name, double percentage, bool isGood)
                {
                    this.Name = name;
                    this.Percentage = (decimal)percentage;
                    this.IsGood = isGood;
                }
                public string Name { get; private set; }
                public decimal Percentage { get; private set; }
                public bool IsGood { get; private set; }
            }



  public static TAttribute GetAttribute<TAttribute>(this Enum value)
        where TAttribute : Attribute
        {
            var type = value.GetType();
            var name = Enum.GetName(type, value);
            return type.GetField(name)
                .GetCustomAttributes(false)
                .OfType<TAttribute>()
                .SingleOrDefault();
        }

这使得这很容易:

        MultiValueEnum enumVar = MultiValueEnum.First;
        var enumStringValue = enumVar.GetAttribute<FooAttribute>().Name;
        var enumValueDecimal = enumVar.GetAttribute<FooAttribute>().Percentage;
        var enumBool = enumVar.GetAttribute<FooAttribute>().IsGood;

7 个答案:

答案 0 :(得分:25)

否则你可以为你的枚举创建一个自定义属性,它可以保存Guid。

这些界限旁边的东西:

class EnumGuid : Attribute
{
    public Guid Guid;

    public EnumGuid(string guid)
    {
        Guid = new Guid(guid);
    }
}

然后你会这样使用它:

enum Project
{
    [EnumGuid("2ED3164-BB48-499B-86C4-A2B1114BF1")]
    Cleanup = 1,
    [EnumGuid("39D31D4-28EC-4832-827B-A11129EB2")]
    Maintenance = 2
    // and so forth, notice the integer value isn't supposed to be used, 
    // it's merely there because not assigning any value is a performance overhead.
}

最后你可以(我总是这样做)创建一个扩展来轻松获取guid:

static Guid GetEnumGuid(this Enum e)
{
    Type type = e.GetType();

    MemberInfo[] memInfo = type.GetMember(e.ToString());

    if (memInfo != null && memInfo.Length > 0)
    {
        object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumGuid),false);
        if (attrs != null && attrs.Length > 0)
            return ((EnumGuid)attrs[0]).Guid;
    }

    throw new ArgumentException("Enum " + e.ToString() + " has no EnumGuid defined!");
}

因此,最后您对枚举的所有要求是:

Guid guid = Project.Cleanup.GetEnumGuid();

我使用这种方法将描述附加到枚举,通常是包含空格的较长字符串,因此不能用作名称。

答案 1 :(得分:11)

我见过SubSonic用来存储Column和Table名称的方法(struct)。

internal struct Project
{
   public static Guid  Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
   public static Guid  Maintenance = new Guid("39D31D4-28EC-4832-827B-A129EB2");
   public static Guid  Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
   public static Guid  Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435");
   public static Guid  Replacement = new Guid("11E5CBA2-EDDE-4ECA-BD63-B725C8C");
   public static Guid  Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F");
   public static Guid  Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190");
   public static Guid  Queries = new Guid("9985242-516A-4151-B7DD-851112F562");
}

编辑: - 感谢评论代码中的缺陷。首先,如果Guid字符串无效,它将编译。至于不创建实例来访问变量是的,他们需要公共静态

答案 2 :(得分:5)

我可能会去这个字典路线。基本上有一个查找表:

public class GuidMapper
{
    private Dictionary<GuidTypes, Guid> mGuidMap = new Dictionary<GuidTypes, Guid>();
    public enum GuidTypes: int
    {
        Cleanup,
        Maintenance,
        Upgrade,
        Sales,
        Replacement,
        Modem,
        Audit,
        Queries
    }

    public GuidMapper()
    {
        mGuidMap.Add(GuidTypes.Cleanup, new Guid("2ED31640-BB48-499B-86C4-A2B1114BF100"));
        mGuidMap.Add(GuidTypes.Maintenance, new Guid("39D31D40-28EC-4832-827B-A11129EB2000"));
        mGuidMap.Add(GuidTypes.Upgrade, new Guid("892F8650-E38D-46D7-809A-49510111C100"));
        mGuidMap.Add(GuidTypes.Sales, new Guid("A5690E70-1111-4AFB-B44D-1DF3AD66D435"));
        mGuidMap.Add(GuidTypes.Replacement, new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C"));
        mGuidMap.Add(GuidTypes.Modem, new Guid("6F686C73-504B-1110-9A0B-850C26FDB25F"));
        mGuidMap.Add(GuidTypes.Audit, new Guid("30558C70-66D9-4189-9BD9-2B87D1119000"));
        mGuidMap.Add(GuidTypes.Queries, new Guid("99852420-516A-4151-B7DD-851112F56200"));
    }

    public Guid GetGuid(GuidTypes guidType)
    {
        if (mGuidMap.ContainsKey(guidType))
        {
            return mGuidMap[guidType];
        }
        return Guid.Empty;
    }
}

答案 3 :(得分:2)

如果您需要正确的enum - 类似语义和类型安全,那么您可以使用这样的模式。

(如果您需要转换操作符,GetUnderlyingTypeToString等额外内容,您可以进一步充实它。如果您想重复使用多个enum的模式 - 类似的类使用不同的底层类型,您可以将任何公共代码移动到通用的抽象基类中。)

Project x = Project.Cleanup;
Project y = Project.Cleanup;
Project z = Project.Maintenance;

Console.WriteLine(x == y);     // True
Console.WriteLine(x == z);     // False
Console.WriteLine(x.Value);    // 47801daa-7437-4bfe-a240-9f7c583018a4

// this line will cause a compiler error
Console.WriteLine(x == new Guid("47801daa-7437-4bfe-a240-9f7c583018a4"));

// ...

public class Project
{
    private Project(Guid v) { Value = v; }
    public Guid Value { get; private set; }

    public static readonly Project Cleanup =
        new Project(new Guid("47801daa-7437-4bfe-a240-9f7c583018a4"));

    public static readonly Project Maintenence =
        new Project(new Guid("2548a7f3-7bf4-4533-a6c1-dcbcfcdc26a5"));

    public static readonly Project Upgrade =
        new Project(new Guid("ed3c3e73-8e6a-4c09-84ae-7f0876d194aa"));
}

答案 4 :(得分:0)

当遇到这种问题时,我使用了具有consts的结构作为公共成员:

public struct FileExtensions
{
    public const string ProcessingExtension = ".lck";
    public const string ProcessedExtension = ".xml";
    public const string FailedExtension = ".failed";
    public const string CsvExtension = ".csv";
}

答案 5 :(得分:0)

您可以创建一个仅包含常量值的静态类。 例如:

internal static class Project
{
    public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
    public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
    public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
}

这样,这个类就像一个容器一样,无法从中创建对象。

在VB中,这将是一个模块:

Friend Module Project
    Public Shared ReadOnly Cleanup As Guid = New Guid("2ED3164-BB48-499B-86C4-A2B1114BF1")
    Public Shared ReadOnly Maintenance As Guid = New Guid("39D31D4-28EC-4832-827B-A11129EB2")
    Public Shared ReadOnly Upgrade As Guid = New Guid("892F865-E38D-46D7-809A-49510111C1")
End Module

答案 6 :(得分:0)

枚举类型可以only support integral types(除了char)作为其值。但是,您可以使用像Dictionary这样的内容来查找值的名称。

Dictionary<Guid> lookup = new Dictionary<Guid>();
lookup["Cleanup"] = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
lookup["Maintenance"] = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
lookup["Upgrade"] = new Guid("892F865-E38D-46D7-809A-49510111C1");
// etc...

另一种方法是在静态类中包含一系列只读值。

public static class Guids
{
  public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
  public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
  public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
}