我的问题最好以一个例子来说明。
假设我有枚举:
public enum ArrowDirection
{
North,
South,
East,
West
}
我想将每个方向对应的单位矢量与该方向相关联。例如,我想要为North返回(0,1),为West返回(-1,0)等等。我知道在Java中你可以在枚举中声明一个可以提供该功能的方法。
我目前的解决方案是使用一个静态方法 - 在定义枚举的类中 - 返回一个对应于传入的ArrowDirection的向量(该方法使用HashTable来完成查找,但这并不重要)。这似乎......不洁净。
问题:
是否有最佳实践解决方案来存储与.NET中枚举相对应的其他信息?
答案 0 :(得分:37)
在C#3.0中有一种奇妙的新方法。关键是这个美丽的事实:枚举可以有扩展方法!所以,这就是你能做的:
public enum ArrowDirection
{
North,
South,
East,
West
}
public static class ArrowDirectionExtensions
{
public static UnitVector UnitVector(this ArrowDirection self)
{
// Replace this with a dictionary or whatever you want ... you get the idea
switch(self)
{
case ArrowDirection.North:
return new UnitVector(0, 1);
case ArrowDirection.South:
return new UnitVector(0, -1);
case ArrowDirection.East:
return new UnitVector(1, 0);
case ArrowDirection.West:
return new UnitVector(-1, 0);
default:
return null;
}
}
}
现在,你可以这样做:
var unitVector = ArrowDirection.North.UnitVector();
甜!我大约一个月前才发现这个问题,但这是新C#3.0功能的一个非常好的结果。
答案 1 :(得分:3)
我在博客上发表了here。
使用Attributes尝试类似的内容。
public enum Status {
[Status(Description = "Not Available")]
Not_Available = 1,
[Status(Description = "Available For Game")]
Available_For_Game = 2,
[Status(Description = "Available For Discussion")]
Available_For_Discussion = 3,
}
public class StatusEnumInfo {
private static StatusAttribute[] edesc;
public static String GetDescription(object e)
{
System.Reflection.FieldInfo f = e.GetType().GetField(e.ToString());
StatusEnumInfo.edesc = f.GetCustomAttributes(typeof(StatusAttribute), false) as StatusAttribute[];
if (StatusEnumInfo.edesc != null && StatusEnumInfo.edesc.Length == 1)
return StatusEnumInfo.edesc[0].Description;
else
return String.Empty;
}
public static object GetEnumFromDesc(Type t, string desc)
{
Array x = Enum.GetValues(t);
foreach (object o in x) {
if (GetDescription(o).Equals(desc)) {
return o;
}
} return String.Empty;
}
}
public class StatusAttribute : Attribute {
public String Description { get; set; }
}
public class Implemenation {
public void Run()
{
Status statusEnum = (Status)StatusEnumInfo.GetEnumFromDesc(typeof(Status), "Not Available");
String statusString = StatusEnumInfo.GetDescription(Status.Available_For_Discussion);
}
}
使用自定义属性
代替描述答案 2 :(得分:1)
using System.ComponentModel;
using System.Reflection;
public enum ArrowDirection
{
[Description("Northwards")]
North,
[Description("Southwards")]
South,
[Description("Eastwards")]
East,
[Description("Westwards")]
West
}
...
创建扩展方法以获取描述列表:
public static class Enum<T> where T : struct
{
/// <summary>
/// Gets a collection of the enum value descriptions.
/// </summary>
/// <returns></returns>
public static IList<string> GetDescriptions()
{
List<string> descriptions = new List<string>();
foreach (object enumValue in Enum<T>.GetValues())
{
descriptions.Add(((Enum)enumValue).ToDescription());
}
return descriptions;
}
}
答案 3 :(得分:0)
您可以看到的一件事是“Type-Safe Enum”模式。这允许你创建一个实际上是一个完整的静态对象的枚举,它可以有方法/属性/等。
http://www.javacamp.org/designPattern/enum.html
Joshua Bloch在他的“Effective Java”一书中讨论了这种模式。我已经在很多不同的情况下使用它,我实际上更喜欢它而不是简单的枚举。 (它与语言无关 - 它适用于Java,C#或几乎任何OO语言)。
答案 4 :(得分:0)
你的静态方法对我来说似乎很干净。您将枚举和静态方法封装在同一个类中。对枚举的更改集中在该单个类中。
在枚举中添加一个方法(根据Java)似乎增加了一些非常简单的概念。
基于属性的方法很有意思,但与静态方法相比,似乎再次使事情过于复杂。