Enum列舉的尋訪、比對並進行變數指派

Enum列舉的尋訪尋值動作並不常用,每次要用的時候都要重新去翻一次System.Enum.GetValues的用法,因此把他筆記這裡,讓有需要的人可以快速地找到使用範例。

已知一整數數值,利用此整數回傳某列舉型別

假設有一列舉行別如下:

enum myFriend
{
	NoFriend = 0,
	John = 1,
	Marry = 2,
	Sam = 3,
	Chris = 4
}

如果我們從前端、或資料庫端得到一個整數數值,那麼我們可以利用下列程式碼比對myFriend裡面所有的列舉項次,並進而取得可能命中的列舉項次。

public static void Main()
{
	int iFriend = 3;
	myFriend eFind = myFriend.NoFriend;
	
	foreach (int iItem in System.Enum.GetValues(typeof (myFriend)))
	{
		if (iFriend == iItem) { eFind = (myFriend)iItem; break; }
	}
	
	Console.WriteLine($"{(int)eFind} / {eFind.ToString()}");
}

利用Linq來進行列舉的查找篩選

如果是把System.Linq弄進來,使用他的語法來進行資料搜尋的話,語法變成一行就可以解決了。這樣的寫法還有一個好處,就是因為enum是實值型別(ValueType),所以就算找不到命中FirstOrDefault也不會傳回null,而是會傳回這個enum的預設值,也就是等於0的NoFriend。(如果列舉裡面沒有等於0的項次,則會回傳一個0,你對它.GetType()還是會回傳myFriend。)

myFriend eFind = System.Enum.GetValues(typeof(myFriend)).OfType<myFriend>().Where(x => (int)x == iFriend).FirstOrDefault();

利用列舉名稱(Enum Name;String)來取得列舉型別本身

有時候我們會希望利用某個Enum的名稱來反轉換(反求得)列舉型別,可以使用下列程式碼來進行:

//Parse寫法
try
{
  var eTemp = System.Enum.Parse(typeof(myFriend), "John");
  Console.WriteLine(eTemp.ToString());
}
catch
{ Console.WriteLine("找不到這個列舉名稱。"); }
//TryParse寫法,這個方法另外有個多載引數可以支援不區分大小寫比對
System.Enum.TryParse("John", out myFriend eTemp);
//如果不存在這個字串而比對失敗,會回傳預設值NoFriend(0)
Console.WriteLine(eTemp.ToString());

利用列舉數值(Enum Value;Int)來取得列舉型別本身

有時候我們會希望利用某個Enum的數值來反轉換(反求得)列舉型別,可以使用下列程式碼來進行:

//傳統轉型寫法
myFriend eTemp = (myFriend)3;
Console.WriteLine(eTemp.ToString());  //印出Sam

//傳統轉型寫法的缺點
myFriend eTemp = (myFriend)123;       //根本沒有此列舉
Console.WriteLine(eTemp.ToString());  //不會出錯且印出123
//使用Enum.IsDefined來輔助檢查
int i = 123;
if(System.Enum.IsDefined(typeof(myFriend), i))
{ 
  myFriend eTemp = (myFriend)i;
  Console.WriteLine(eTemp.ToString());
}
else
{ Console.WriteLine("找不到這個列舉數值。"); }

要特別注意的是,當Enum被套用了[System.Flags] Attributes屬性時Enum.IsDefined將會失效(失去判斷作用),如果你有到這麼深的程度,要自己特別小心。

Happy Coding!

參考文章:

Enum用於位元邏輯運算的寫法

System.Enum.GetValues System.Enum.GetNames Foreach Int32 Assignment IntToEnum StringToEnum ConvertToEnum