2009-07-08 74 views
24

由於枚舉使用整數,我可以用什麼樣的結構,給我掛的名稱值枚舉類訪問:枚舉與字符串以外的返回類型?

[我知道這是不對的,尋找替代]

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年7月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; 

回答

22

否則,您可以爲您的枚舉創建自定義屬性,該屬性可以容納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(); 

我使用這種方法來將說明附加到枚舉上,通常是包含空格的較長字符串,因此不能用作名稱。

11

我見過使用亞音速存儲列和表名這種方法(結構)。

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字符串不是無效的,它將被編譯。至於不創建實例訪問的變量是他們需要公共靜態

+1

無法訪問結構中的專用字段,也無法像在結構中那樣初始化字段。 – leppie 2009-07-08 11:01:28

+3

他們需要也是靜態的,例如工作。 – leppie 2009-07-08 11:02:09

+0

你不應該能夠創建這個結構體的實例,因爲它只能作爲一個容器來使用 – 2009-07-08 11:05:03

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

枚舉類型可以only supportintegral types作爲其值(除炭)。然而,你可以使用像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"), 
} 
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; 
    } 
} 
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")); 
}