C#列舉(一)使用總結以及擴充套件類分享

Iannnnnnnnnnnnn發表於2021-02-08

0.介紹

列舉是一組命名常量,其基礎型別為任意整型。 如果沒有顯式宣告基礎型別, 則為Int32

在實際開發過程中,列舉的使用可以讓程式碼更加清晰且優雅。

最近在對列舉的使用進行了一些總結與整理,也發現了一些很有意思的知識盲區。

接下來先簡單為大家介紹列舉在開發過程中的常用內容以及擴充套件類的分享。如果喜歡直接看程式碼的可以檢視最後的樣例原始碼。

1. 參考資料

官方Doc https://docs.microsoft.com/zh-cn/dotnet/api/system.enum?view=net-5.0

部落格 https://www.cnblogs.com/kissdodog/archive/2013/01/16/2863515.html

部落格 https://www.cnblogs.com/willick/p/csharp-enum-superior-tactics.html

2.核心內容

  • 列舉的使用心得

0.列舉數值在開發過程中一旦確定不允許更改(除非必要 )

1.在定義列舉的時候要設定0值,且不作為有效的業務值。(不作為有效值的原因是列舉的初始化值為零,在沒有正確賦值的情況下,已經有預設值可能會造成困擾,所以直接不使用0作為業務有效值,可以省去不必要的麻煩,這半點純屬個人建議~)

這一點官方文件也有“最佳做法”的建議。

如果未定義值為0的列舉成員,則考慮建立 None 列舉常數。 預設情況下,由公共語言執行時將用於列舉的記憶體初始化為零。 因此,如果未定義值為零的常量,則在建立列舉時將包含非法值。

2.在前後端互動過程中,如果後端接收的物件中包含列舉的話,需要將列舉屬性定義成可空列舉,否則前端資料有可能(前端屬性值在後端的列舉值中匹配不上時)無法傳輸到後端。

3.資料庫儲存列舉值而非列舉屬性字串

雖然儲存列舉屬性字串會更加直觀,但是不利於後續列舉字串重新命名,且字串長度限制也制約著列舉的命名...

  • 列舉的基本用法

定義列舉

列舉並不顯式從繼承 Enum ; 繼承關係由編譯器隱式處理

// 列舉YesOrNo
public enum YesOrNo
{
    [Description("")]
    None = 0,
    [Description("是")]
    Yes = 1,
    [Description("否")]
    No = 2
}

// 列舉YesOrNo 基礎型別為byte
public enum YesOrNo_Byte : byte
{
    [Description("")]
    None = 0,
    [Description("是")]
    Yes = 1,
    [Description("否")]
    No = 2
}
列舉 => 轉字串
string yesString = YesOrNo.Yes.ToString(); // Yes
列舉 => 轉數字
int yesInt = (int)YesOrNo.Yes; // 1
字串 => 列舉
YesOrNo yesOrNo_Yes = (YesOrNo)Enum.Parse(typeof(YesOrNo), "Yes"); // YesOrNo.Yes
數字 => 列舉
YesOrNo yesOrNo_No = (YesOrNo)2; // YesOrNo.No
獲取所有的列舉成員
Array yesOrNos = Enum.GetValues(typeof(YesOrNo)); // [YesOrNo.None,YesOrNo.Yes,YesOrNo.No]
獲取所有列舉成員的屬性名
string[] yesOrNoNames = Enum.GetNames(typeof(YesOrNo)); // ["None","Yes","No"]
獲取枚的舉基礎型別
Type typeInt = Enum.GetUnderlyingType(typeof(YesOrNo)); // System.Int32
    
Type typeByte = Enum.GetUnderlyingType(typeof(YesOrNo_Byte)); // System.Byte
  • 擴充套件方法

字串 => 轉列舉
// GetEnum()  字串 => 轉列舉
var yesString = "Yes".GetEnum<YesOrNo>(); // YesOrNo.Yes

/// <summary>
/// 根據字串轉成指定列舉值
/// </summary>
public static T GetEnum<T>(this string enumString)
{
    return (T)Enum.Parse(typeof(T), enumString);
}
列舉 => 轉數字
// GetIntValue() 列舉 => 轉數字
int yesInt = YesOrNo.Yes.GetIntValue(); // 1

/// <summary>
/// 獲取列舉的值
/// </summary>
public static int GetIntValue(this Enum value)
{
    return Convert.ToInt32(value);
}            
獲取列舉的描述
// GetDescription()  獲取列舉的描述
var description = YesOrNo.Yes.GetDescription(); // 是

/// <summary>
/// 根據列舉獲取列舉描述
/// </summary>
public static string GetDescription(this Enum value)
{
    var field = value.GetType().GetField(value.ToString());
    var customAttribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
    if (customAttribute == null)
        return value.ToString();
    else
        return ((DescriptionAttribute)customAttribute).Description;
}          
將列舉字串值與描述轉字典
// GetEnumDescriptions() 獲取列舉字串值與描述
var dictionary = typeof(YesOrNo).GetEnumDescriptions(); // {{[None, ""]},{[Yes, 是]},{[No, 否]}}

/// <summary>
/// 獲取列舉字串值及描述值的字典
/// </summary>

public static IDictionary<string, string> GetEnumDescriptions(this Type enumType)
{
    var dictionary = new Dictionary<string, string>();
    foreach (Enum code in Enum.GetValues(enumType))
        dictionary.Add(code.ToString(), code.GetDescription());

    return dictionary;
}         
將列舉值與描述轉字典
// GetEnumIntDescriptions() 獲取列舉值與描述
var intDictionary = typeof(YesOrNo).GetEnumIntDescriptions(); // {{[0, ""]},{[1, 是]},{[2, 否]}}

/// <summary>
/// 獲取列舉值及描述值的字典
/// </summary>

public static IDictionary<int, string> GetEnumIntDescriptions(this Type enumType)
{
    var dictionary = new Dictionary<int, string>();
    foreach (Enum code in Enum.GetValues(enumType))
        dictionary.Add(code.GetIntValue(), code.GetDescription());

    return dictionary;
}        

3.樣例原始碼地址

https://github.com/Impartsoft/Bins/tree/main/EnumDemo

相關文章