tags:

views:

626

answers:

7

Since enumeration uses integers, what other structure can I use to give me enum-like access to the value linked to the name:

[I know this is wrong, looking for alternative]

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")
    }
+4  A: 

I've seen this method (struct) used by SubSonic to store Column and Table names.

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

EDIT:- Thanks for commenting on deficiencies in code. In first place it will compile if the Guid strings are not invalid. As for not create instances to access variables yes they need to be public static

TheVillageIdiot
Can't access private fields in structs, also cant initialize fields like you do in a struct.
leppie
They will need to be static too, for your example to work.
leppie
You shouldn't be able to create instances of this struct, since it acts only as a container
Enrico Campidoglio
Well it wont compile for more than 1 reason.
leppie
+1 to @leppie for pointing out static thing.
TheVillageIdiot
Make it a static class. This is the same thing as Brushes.Black and so on.
Daniel Earwicker
A: 

When confronted with this kind of problem I used structs with consts as public members:

public struct FileExtensions
{
 public const string ProcessingExtension = ".lck";
 public const string ProcessedExtension = ".xml";
 public const string FailedExtension = ".failed";
 public const string CsvExtension = ".csv";
}
Oded
A class will make more sense, given you can derive from it, and extend the constants.
leppie
I wouldn't derive from a class whose only purpose is to contain constant values, since polymorphism wouldn't make much sense. Instead I would keep adding related constants to the same class, or create new ones for new sets of constants.
Enrico Campidoglio
@enrico: there are a few benefits, like the parents fields being in scope.
leppie
using public const Guid Cleanup = new Guid("2E43264-BB48-432B-86C4-A2B1114BF1");in oublic struc I get build error: "cannot have field initialisers in structs." and "System.Guid cannot be declared const"
callisto
Why do people gravitate toward struct for this?
Daniel Earwicker
Because of the Value type semantics structs and enums share.
Oded
@Oded: that is completely irrelevant.
leppie
A: 

You could create a static class that just contains constant values. For example:

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

This way the class acts simply as a container and object cannot be created from it.

In VB this would be a Module:

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
Enrico Campidoglio
Guid cant be const....
leppie
You are right, I changed them to read-only fields
Enrico Campidoglio
Here we go still. Static classes cant have instance members!
leppie
Right once again :-)
Enrico Campidoglio
A: 

The enum type can only support the integral types (except char) as its value. You could however use something like a Dictionary to do lookups of a a name to a value.

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...

Another alternative is to have a series of readonly values in a static class.

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"),
}
heavyd
Here we go again. Static classes cant have instance members!
leppie
Good point, thanks. Updated
heavyd
+6  A: 

Otherwise you could create a custom Attribute for your enum, which can hold the Guid.

Something alongside these lines:

class EnumGuid : Attribute
{
    public Guid Guid;

    public Description(Guid guid)
    {
     this.Guid = guid;
    }
}

And you'd then use it like so:

enum Project
{
    [EnumGuid(new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"))]
    Cleanup = 1,
    [EnumGuid(new Guid("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.
}

And finally you could (I always do this) create an extension for easily getting the 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(Description),
             false);
  if (attrs != null && attrs.Length > 0)
   return ((EnumGuid)attrs[0]).Guid;
 }

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

So in the end all you have to with your enums is:

Guid guid = Project.Cleanup.GetEnumGuid();

I use this approach to attach descriptions to enums, typically longer strings containing spaces, which thus cannot be used as names.

Steffen
+2  A: 

I would probably go the dictionary route on this one. Have a lookup table basically:

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;
    }
}
SwDevMan81
+1  A: 

If you need proper enum-like semantics and type-safety then you can use a pattern like this.

(You could flesh it out further if you require extras like conversion operators, GetUnderlyingType, ToString etc. If you wanted to re-use the pattern for multiple enum-like classes with different underlying types then you could move any common code into a generic, abstract base class.)

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"));
}
LukeH