Enums unter C#
Frank Dzaebel, Quelle:u.a. Artikel über Enums, erstellt am: 21.1.2006, zuletzt geändert: 17.2.2006
Kategorie: Implementation, .NET-Version: 2.0
[Dieser Artikel dient relevanter Code & Informations-Sammlung bzgl. Enums]
-
Test-Version completionlist-Hack in C#.
-
U.a. Ralf Wesphal's generische "Set"-Klasse. John Skeet's "Enhanced Enums in C#".
-
Java 5.0 Enum's: In früheren Versionen von Java war ein Enum wie in C/C++/C# letztlich nur ein int. Genauer, es gab keine Enums! Dies wurde in Java 5.0 geändert. Doch sie haben hier eine weitergehende Semantik, als in .NET.
- Empfohlener Enumerationsentwurf in C#.
- Design Guidelines Update: Enum Design
Completionlist-Hack in C#
using System;
using System.Collections.Generic;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
namespace Enums
{
#region class WindowPart
/// <completionlist cref="WindowParts"/>
[TypeConverter(typeof(WindowPartsConverter))]
public class WindowPart
{
private string name;
public WindowPart(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
public override string ToString()
{
return name;
}
}
#endregion class WindowPart
#region class WindowParts
public sealed class WindowParts
{
private WindowParts() {}
public static WindowPart Border
{
get { return new WindowPart("Border"); }
}
public static WindowPart TitleBar
{
get { return new WindowPart("TitleBar");}
}
public static WindowPart ClientArea
{
get { return new WindowPart("ClientArea"); }
}
}
#endregion class WindowParts
#region class WindowPartsConverter
public class WindowPartsConverter : EnumConverter
{
public WindowPartsConverter(Type type) : base(type) { }
public override bool CanConvertFrom(ITypeDescriptorContext context,Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context,CultureInfo culture,object value)
{
if (value is String)
return new WindowPart((string)value);
else
throw new ArgumentException("'value' must be of type 'String'.");
}
public override bool CanConvertTo(ITypeDescriptorContext context,Type destinationType)
{
return destinationType == typeof(WindowPart);
}
public override object ConvertTo(ITypeDescriptorContext context,CultureInfo culture,object value,Type destinationType)
{
return ((WindowPart)value).Name;
}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
// Bestimmen der gemeinsamen Eigenschaften des Typs "WindowPart".
List<WindowPart> standardValues = new List<WindowPart>();
PropertyInfo[] sharedProperties =
typeof(WindowParts).GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (PropertyInfo prop in sharedProperties)
standardValues.Add((WindowPart)prop.GetValue(typeof(WindowParts),null));
return new StandardValuesCollection(standardValues);
}
}
#endregion class WindowPartsConverter
}
Ralf Wesphal's generische Set-Klasse:
using System.Collections.Generic;
using System;
using System.Text;
public class Set<TEnum>
{
#region "Data"
bool flagsEnum;
System.Collections.BitArray members;
System.Collections.Generic.Dictionary<TEnum,int> mapMember2Index;
#endregion
#region "ctors"
public Set()
{
Initialize();
members = new System.Collections.BitArray(mapMember2Index.Count);
}
private Set(System.Collections.BitArray members)
{
Initialize();
this.members = members;
}
private void Initialize()
{
if (typeof(TEnum).BaseType != typeof(System.Enum))
throw new ApplicationException(string.Format(
"Generic type parameter <{0}> is not an enum type!",
typeof(TEnum).FullName));
flagsEnum = typeof(TEnum).GetCustomAttributes(typeof(
System.FlagsAttribute),true).Length > 0;
int i = 0;
mapMember2Index = new Dictionary<TEnum,int>();
foreach (TEnum m in Enum.GetValues(typeof(TEnum)))
mapMember2Index.Add(m,i++);
}
#endregion
#region "Working with the set"
public void Clear()
{
members.SetAll(false);
}
public Set<TEnum> Add(TEnum member)
{
members.Set(mapMember2Index[member],true);
return this;
}
public Set<TEnum> Add(Set<TEnum> otherSet)
{
if (otherSet != null) members.Or(otherSet.members);
return this;
}
public Set<TEnum> Remove(TEnum member)
{
members.Set(mapMember2Index[member],false);
return this;
}
public Set<TEnum> Remove(Set<TEnum> otherSet)
{
if (otherSet != null)
for (int i = 0; i < members.Count; i++)
if (otherSet.members[i])
members[i] = false;
return this;
}
public Set<TEnum> Intersect(Set<TEnum> otherSet)
{
if (otherSet != null) members.And(otherSet.members);
return this;
}
public bool Contains(TEnum member)
{
return members[mapMember2Index[member]];
}
public int Cardinality
{
get
{
return members.Length;
}
}
#endregion
#region "Overrides"
public override bool Equals(object obj)
{
return this == (Set<TEnum>)obj;
}
public override int GetHashCode()
{
return members.GetHashCode();
}
public override string ToString()
{
string[] names = Enum.GetNames(typeof(TEnum));
StringBuilder memberNames = new StringBuilder("[");
for (int i = 0; i < members.Count; i++)
if (members[i])
{
if (memberNames.Length > 1) memberNames.Append(",");
memberNames.Append(names[i]);
}
memberNames.Append("]");
return memberNames.ToString();
}
#endregion
#region "Operators"
/// <summary>Intersection</summary>
public static Set<TEnum> operator &(Set<TEnum> left,Set<TEnum> right)
{
System.Collections.BitArray result = new System.Collections.BitArray(new bool[left.members.Count]);
result.Or(left.members);
if (right != null) result.And(right.members);
return new Set<TEnum>(result);
}
/// <summary>Union</summary>
public static Set<TEnum> operator |(Set<TEnum> left,Set<TEnum> right)
{
System.Collections.BitArray result = new System.Collections.BitArray(
new bool[left.members.Count]);
result.Or(left.members);
if (right != null) result.Or(right.members);
return new Set<TEnum>(result);
}
public static bool operator ==(Set<TEnum> left,Set<TEnum> right)
{
if (right != null)
{
for (int i = 0; i < left.members.Count; i++)
if (left.members[i] != right.members[i]) return false;
return true;
}
else return false;
}
public static bool operator !=(Set<TEnum> left,Set<TEnum> right)
{
return !(left == right);
}
#endregion
#region "Iterator"
public IEnumerator<TEnum> GetEnumerator()
{
TEnum[] memberValues = (TEnum[])Enum.GetValues(typeof(TEnum));
for (int i = 0; i < members.Count; i++)
if (members[i]) yield return memberValues[i];
}
#endregion
}