重學c#系列——列舉[二十三]

2022-11-20 15:09:04

前言

該系列繼續更新,列舉介紹。

正文

首先呢,列舉是值型別,這個沒什麼好說的。

enum ConnectionState 
{
	DisConnected,
	Connecting,
	Connected,
	DisConnecting
}

如果不顯示命名的情況下呢?第一個DisConnected為0,Connecting 為1。

enum ConnectionState 
{
	DisConnected,
	Connecting=100,
	Connected,
	DisConnecting
}

如果Connecting 被設定為100了,那麼connected 就是101,DisConnecting 就是102。

列舉支援不同型別之間的列舉轉換,但是兩種的值要相等。

但是陣列並不能直接轉換:

先轉換成array,然後再轉換成ConnectionState2 是可以的:

數位轉列舉,一般就是之間顯示轉換就可以了。

即使這個值不存在,轉換也不會存在問題:

這個時候a.tostring()就是100,不然的話就會輸出我們定義的字串了。

那麼如果將字串轉換為列舉呢?

internal class Program
{
	static void Main(string[] args)
	{
		if (Enum.TryParse<ConnectionState>("DisConnected", out ConnectionState value))
		{
			Console.WriteLine(value.ToString());
		}
		Console.ReadKey();
	}
}

如果用parse,那麼如果字串沒有和列舉匹配的那麼會報錯。

然後列舉還有一個比較好的功能那就是可以多選。

這種情況就是列舉作為標誌位使用。

其實原理很簡單,利用的是二進位制這個設計。

比如:
000000000000000001
000000000000000010
那麼他們相加之後就是:000000000000000011

這個只要知道哪一個位數上有,那麼哪個就被選中了。

官方使用比較多的例子是system.io 中:

[Flags]
public enum FileAttributes
{
	ReadOnly = 0x0001,
	Hidden = 0x0002,
	System = 0x0004,
	Directory = 0x0010,
	Archive = 0x0020,
	Device = 0x0040,
	Normal = 0x0080,
	Temporary = 0x0100,
	SparseFile = 0x0200,
	ReparsePoint = 0x0400,
	Compressed = 0x0800,
	Offline = 0x1000,
	NotContentIndexed = 0x2000,
	Encrypted = 0x4000,
	IntegrityStream = 0x8000,
	NoScrubData = 0x20000
}

這裡面就有很多組合,比如ReadOnly 和Hidde 等等,這裡就不舉例了。

static void Main(string[] args)
{
	FileInfo fileInfo = new FileInfo("c:/test.txt");
	fileInfo.Attributes = FileAttributes.Hidden| FileAttributes.ReadOnly;
	Console.ReadKey();
}

上面就是說明將這個檔案資訊設定為隱藏且唯讀的吧。| 符合為:如果存在於任一運算元中,二進位制 OR 運運算元複製一位到結果中。

當然,如果有一些組合你已經知道了,那麼你可以在列舉中就處理:

[Flags]
enum MyEnum
{
	high = 1,
	rich = 2,
	graceful = 4,
	hrq = high | rich | graceful
}

然後很多人建議在flags 中都有一個none 為0的列舉,表示一個都沒有選:

[Flags]
enum MyEnum
{
	none = 0,
	high = 1,
	rich = 2,
	graceful = 4,
	hrq = high | rich | graceful
}

然後這裡解釋一下,我們為什麼要使用Flags。

我們知道原理後,其實不使用flags也是可以實現的。

enum MyEnum
{
	none = 0,
	high = 1,
	rich = 2,
	graceful = 4,
	hrq = high | rich | graceful
}

那麼這個flags 給我們帶來了什麼呢?

static void Main(string[] args)
{
	var test = MyEnum.high | MyEnum.rich;
	Console.WriteLine(test.ToString());
}

當我們tostring的時候:

給我們返回了high, rich,如果沒有這個flags的話,那麼返回的是3。

那麼可以string 用逗號可以轉換為,如果沒有flags,那麼就轉換不了:

因為enum 根據enum 走的是不同的方法:

private static string? InternalFormat(RuntimeType enumType, ulong value)
{
	EnumInfo enumInfo = GetEnumInfo(enumType);

	if (!enumInfo.HasFlagsAttribute)
	{
		return GetEnumName(enumInfo, value);
	}
	else // These are flags OR'ed together (We treat everything as unsigned types)
	{
		return InternalFlagsFormat(enumType, enumInfo, value);
	}
}

該系列繼續更新。