Wednesday, January 16, 2008

Instead of Enum

Since I tend to ramble I'll start this out with the code.



using System;
using System.Collections.Generic;
using System.Reflection;

public class MyEnum
{
#region Fields
private int id;

// Other values
private string name;
private bool archived_flag;
#endregion

#region Static Pre-defined instances (this is the enum)
public static readonly MyEnum Empty = MyEnum.Factory(-999, string.Empty);
public static readonly MyEnum First = MyEnum.Factory(1, "First Item");
public static readonly MyEnum Second = MyEnum.Factory(2, "Second Item");
public static readonly MyEnum Third = MyEnum.Factory(3, "Third Item");
public static readonly MyEnum Fourth = MyEnum.Factory(4, "Fourth Item");
#endregion

#region Constructors
private MyEnum()
{

}
#endregion

#region Properties
public string ID
{
get
{
return this.id;
}
}
public string Name
{
get
{
return this.name;
}
}

#endregion

private static MyEnum Factory(int id, string name)
{
MyEnum me = new MyEnum();
me.id = id;
me.name = name;

return me;
}

public static MyEnum GetByID(int id)
{
if (lAll == null) { MyEnum.GetAll(); }
foreach (MyEnum me in lAll)
{
if (me.id == id)
{
return me;
}
}
return MyEnum.Empty;
}

public static List lAll = null;

public static List GetAll()
{

if (lAll == null)
{
lAll = new List();

Type myType = typeof(MyEnum);
FieldInfo[] fields = myType.GetFields();

foreach (FieldInfo fi in fields)
{
if (fi.FieldType == myType && fi.IsStatic && fi.IsPublic)
{
MyEnum value = fi.GetValue(null) as MyEnum;
if (value != null)
{
lAll.Add(value);
}
}
}
}

return lAll;

}

#region Operators
public override bool Equals(object obj)
{
if (obj == null) return false;

MyEnum co = obj as MyEnum;
if ((object)co == null) // Cast to avoid calling the override == operator
{
return false;
}

return this.Equals(co);
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public bool Equals(MyEnum me)
{
return (object)me == null ? false : this.ID.Equals(me.ID);
}
public static bool operator ==(MyEnum a, MyEnum b)
{
// If the same instance or both null then return true
if (System.Object.ReferenceEquals(a, b))
{
return true;
}

// If one is null return false
if ((object)a == null (object)b == null) // Cast to avoid calling the override == operator
{
return false;
}

return a.Equals(b);
}
public static bool operator !=(MyEnum a, MyEnum b)
{
return !(a == b); // This calls the override operator above
}
#endregion

public override string ToString()
{
return this.Name;
}

}


I use this pattern as a replacement for almost all my former enums. Using classes like the one above you get a simple type with a set of pre-defined, valid, values (like an enum). It's type-safe. It handles equals(), == and !=. It also allows you to add properties and methods to each value which provides much more programming power.