[英]java enums vs C# enums - missing features
在java中,我可以輕松地描述帶有aditional數據的枚舉。
我可以形容這樣的事情
public enum OperatorType
{
GreaterOrEqual (">=", "GreaterOrEqual"),
Greater (">" ,"Greater"),
Less ("<", "Less"),
LessOrEqual ("<=", "LessOrEqual"),
Equal ("==", "Equal"),
Between ("Between", "Between"),
Around ("Around","Around");
private final String symbol;
private final String name;
private OperatorType(final String symbol, final String name) {
this.symbol = symbol;
this.name = name;
}
}
然后添加一個迭代values()的靜態方法,將所有數據添加到hashmap中,並允許通過其中一個屬性從映射中檢索完整枚舉數據作為鍵。
簡而言之,enum是java中非常發達的類型。
現在,
轉到c#,我的選擇是什么?
我想要保存帶有屬性的枚舉,將其加載到地圖中,並在需要時按鍵進行檢索。 我有什么需要幫助的嗎(比如每個枚舉的單音 - 這不是一個好主意)。
謝謝。
我只想創建一個類,每個類型的public static readonly
實例和ditch枚舉。 您可以將它們用作字典鍵或做任何您喜歡的事情。 如果您仍打算將它們映射到基礎數據類型( int
),那么您也可以為它創建隱式運算符。
public class OperatorType
{
private static readonly Dictionary<int, OperatorType> OperatorMapping = new Dictionary<int, OperatorType>();
public static readonly OperatorType GreaterOrEqual = new OperatorType(0, ">=", "GreaterOrEqual");
public static readonly OperatorType Greater = new OperatorType(1, ">", "Greater");
public readonly String symbol;
public readonly String name;
private readonly int underlyingValue;
private OperatorType(int underlyingValue, string symbol, string name) {
this.underlyingValue = underlyingValue;
OperatorMapping[underlyingValue] = this;
this.symbol = symbol;
this.name = name;
}
public static implicit operator int(OperatorType operatorType)
{
return operatorType.underlyingValue;
}
public static implicit operator OperatorType(int value)
{
return OperatorMapping[value];
}
}
樣品用法:
Dictionary<OperatorType, string> operators = new Dictionary<OperatorType, string>();
operators.Add(OperatorType.GreaterOrEqual, "Greater or equal");
Console.WriteLine(operators[OperatorType.GreaterOrEqual]); //"Greater or equal"
OperatorType operatorType = 1;
Console.WriteLine(operatorType.name); //"Greater"
如果您不關心基礎值,請不要包含它。 還要考慮Dictionary
映射是否應該是您使用的線程安全。 您還可以公開靜態IEnumerable<OperatorType>
(或其他集合),以便根據需要定義所有運算符。
編輯:第二個想法, explicit
運算符可能更可取而不是implicit
,既符合典型的.NET最佳實踐,又更符合典型的enum
轉換。
最方便的解決方法可能是為枚舉類型創建擴展方法,並返回關聯的符號。
像這樣的東西:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
tester t = tester.x;
t.testenums();
Console.ReadKey();
}
}
public static class ext
{
public static void testenums(this tester x)
{
Console.WriteLine(x.ToString());
}
}
public enum tester
{
x,
y
}
}
當然你可以編寫一個更復雜的擴展方法,帶有返回值等,這只是一個如何做的例子。
C#實際上沒有相同的功能。 然而,有幾種可能性非常接近(也可能更靈活)。
堅持常規枚舉,您可以使用屬性來豐富額外信息。 當然,這需要反思才能實現
public enum OperatorType
{
[DisplayName(">=")]
GreaterOrEqual,
// ...
}
有幾種模式可以解決這個問題,例如http://www.codeproject.com/Articles/28087/DisplayNameAttribute-for-Enumerations,google了解更多。
另一種方法是使用常規類來增強枚舉類型:
public class OperatorType
{
public static OperatorType GreaterOrEqual = new OperatorType(">=", "GreaterOrEqual");
// ...
string symbol;
string name;
private OperatorType(string symbol, string name)
{
this.symbol = symbol;
this.name = name;
}
}
本文介紹了在C#中使用類似枚舉類型的一些其他方法
您可以創建一個屬性:
public class EnumKeyAttribute : Attribute
{
public string Key { get; set; }
public string Description { get; set; }
public EnumKeyAttribute(string key, string description)
{
this.Key = key;
this.Description = description;
}
}
然后將它應用到你的枚舉
public enum OperatorType
{
[EnumKey(">=", "GreaterOrEqual")]
GreaterOrEqual,
[EnumKey(">", "Greater")]
Greater,
[EnumKey("<", "Less")]
Less,
[EnumKey("<=", "LessOrEqual")]
LessOrEqual,
[EnumKey("==", "Equal")]
Equal,
[EnumKey("Between", "Between")]
Between,
[EnumKey("Around", "Around")]
Around
}
要獲取屬性數據,您可以使用反射。 以下是獲取“Less”屬性的示例
MemberInfo memberInfo = typeof(OperatorType).GetMember(OperatorType.Less.ToString()).FirstOrDefault();
if(memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
Console.WriteLine(attribute.Key);
Console.WriteLine(attribute.Description);
}
但是因為這些枚舉不是在運行時創建的,所以可以通過創建一個在字典中查找值的靜態方法來提高效率。 這是一種易於使用的擴展方法
public static class KeyFinder
{
private static Dictionary<OperatorType, EnumKeyAttribute> lookupTable =
new Dictionary<OperatorType, EnumKeyAttribute>();
public static EnumKeyAttribute GetKey(this OperatorType type)
{
if (lookupTable.ContainsKey(type))
{
return lookupTable[type];
}
MemberInfo memberInfo = typeof(OperatorType).GetMember(type.ToString()).FirstOrDefault();
if (memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
if (attribute != null)
{
lookupTable.Add(type, attribute);
return attribute;
}
}
// add a null value so next time it doesn't use reflection only to find nothing
lookupTable.Add(type, null);
return null;
}
}
所以現在要獲取值,您只需執行以下操作:
OperatorType.Less.GetKey().Key
OperatorType.Less.GetKey().Description
請注意空引用異常(因為如果找不到屬性,它將返回null)。 如果要按鍵查找,只需創建其他使用字符串值作為鍵的擴展方法。
如果您確實需要C#中Java風格枚舉的功能,我會看到三種合理的方法來實現它:
使用C#枚舉和靜態類輔助方法。 你失去了類型安全性,但這是一個非常可行的解決方案。
使用C#枚舉和一組擴展方法。 可能是最慣用的C#解決方案,但您仍然必須處理類型安全性的損失(您的擴展方法應該能夠處理超出范圍的值,即使只是拋出異常)。
在Java 5中獲得enum
關鍵字的語言之前,使用Java中常見的類型安全枚舉模式 。如果每個枚舉值都有非平凡的邏輯,那么這將是我的偏好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.