《隨筆十》——C#中的 “ 列舉 ”
目錄
列舉
● 列舉是由程式設計師自定義的型別:
與結構一樣,列舉是值型別, 因此直接儲存它們的資料,而不是分開儲存引用和資料。
列舉只有一種型別的成員: 命名的整數值常量。
● 列舉: 允許定義一個 列舉型別名,然後用列舉型別名宣告的變數,其變數的值只能取自 括號內的這些識別符號。
enum 列舉型別識別符號 : 可取的基本型別
{
//列舉成員常量
}
注意:如果沒有寫可取的基本型別, 預設情況下該型別為int。 列舉的基本型別可以是: byte sbyte short ushort int uint long ulong. 列舉的型別是任何整數型別。
其中,每個列舉成員常量都被賦予一個底層型別的常量值。 該成員常量的值可以是可取的基本型別的該型別的任何值。
在預設情況下, 編譯器把每一個成員賦值為0,並對每一個後續成員賦的值比前一個成員多1.
要顯式地設定一個成員的名稱,在列舉宣告中的變數名之後使用初始化表示式。 儘管不可以有重複的名稱,但是可以有重複的值。或者說 還可以使用一個值(列舉常量)作為另一個列舉(列舉常量)的基礎值,為多個列舉指定相同的值(不過要注意的是: 這裡可能產生預料不到的問題。).(C++中不可以這樣):
namespace Ch05Ex03 { enum Light:uint { value1=22, value2, value3 = value1, value4, value5=22 } class Program { static void Main(string[] args) { Light myLight1 = Light.value1; Light myLight2 = Light.value2; Light myLight3 = Light.value3; Light myLight4 = Light.value4; Light myLight5 = Light.value5; Light myLight6 = myLight5; // 還可以使用同類型的列舉變數複製值,myLight6 是 myLight5 的副本 WriteLine($"輸出myLight1的值 {myLight1}——{(int)myLight1}"); WriteLine($"輸出myLight2的值:{myLight2}——{(int)myLight2}"); WriteLine($"輸出myLight3的值:{myLight3}——{(int)myLight3}"); WriteLine($"輸出myLight4的值:{myLight4}——{(int)myLight4}"); WriteLine($"輸出myLight5的值:{myLight5}——{(int)myLight5}"); WriteLine($"輸出myLight6的值:{myLight6}——{(int)myLight6}"); ReadKey(); } } } 輸出結果為: 輸出myLight1的值 value5——22 輸出myLight2的值:value4——23 輸出myLight3的值:value5——22 輸出myLight4的值:value4——23 輸出myLight5的值:value5——22 輸出myLight6的值:value5——22
注意: 以迴圈的方式賦值可能會產生錯誤。
enum Light:uint
{
value2 = value1, //錯誤
value1 = value2,
}
列舉值與整型值的轉換
namespace HelloWorld_Console { enum orientation : byte { north = 1, south = 2, east = 3, west = 4 } class Program { static void Main(string[] args) { orientation myDirection = orientation.north; WriteLine($"myDirection = {myDirection}"); WriteLine(orientation.north); ReadKey(); } } } 輸出結果為: myDirection = north north
仔細看這個程式當我們輸出列舉型別建立的變數時輸出的值是列舉成員的列舉值,而不是整數值。如果想把列舉值變成整數值,需要顯式轉換。
下面看一個程式列舉值轉換整數值:
namespace HelloWorld_Console
{
enum orientation : byte
{
north,
south,
east = 3,
west = 4
}
class Program
{
static void Main(string[] args)
{
orientation myDirection = orientation.north;
WriteLine($"myDirection = {myDirection}");
// 把 myDirection 的值轉換為 byte 型別,必須用顯式轉換
byte directionByte = (byte)myDirection;
string directionString = Convert.ToString(myDirection); // 也可以使用變數本身的myDirection.ToString() 命令,效果相同;
WriteLine($"byte equivalent = {directionByte}");
WriteLine($"string equivalent = {directionString}");
//將byte 型別轉換為 orientation,也同樣需要進行顯式轉換。
byte myByte = 4; //如果這裡寫7,即超過了列舉列表中的值,就會直接輸出7,不會轉換
myDirection = (orientation)myByte;
WriteLine($"string equivalent = {myDirection}\n");
string myString = " west "; //這裡只能寫列舉常量中的任何一個列舉值,否則的話,錯誤
orientation myDirection11 = (orientation)Enum.Parse(typeof(orientation), myString);
WriteLine($"把mystring 的值轉換成列舉值:{myDirection11}");
ReadKey();
}
}
}
輸出結果為:
myDirection = north
byte equivalent = 0
string equivalent = north
string equivalent = west
把mystring 的值轉換成列舉值:west
注意: 列舉型別變數的取值範圍只可以是 列舉中的列舉常量列表中的任何一個, 不可以是除了列舉常量的其他值。
在本例中雖然 orientation 的基本型別是 byte , 但是必須使用(byte) 強制型別轉換, 把 myDirection 的值轉換為 byte 型別。
同理, 如果要將byte 型別轉換為 orientation,也同樣需要進行顯式轉換。
● 要獲得列舉的字串值,可以使用 Convert.ToString();
注意: 這裡使用 (string) 強制型別轉換是不行的,因為需要進行的處理並不僅是把儲存在列舉變數中的資料放在string 變數中。
還可以使用變數本身的ToString() 命令, 效果一樣:
directionString = myDirection.ToString();
● 也可以把 string 轉換為,列舉值, 使用 Enum.Parse() , 語法為:
(列舉的型別)Enum.Parse(typeof(列舉的型別),要轉換的string變數)
例如:
string myString = " west "; //這裡只能寫列舉常量中的任何一個列舉值,否則的話,錯誤
orientation myDirection11 = (orientation)Enum.Parse(typeof(orientation), myString);
WriteLine($"把mystring 的值轉換成列舉值:{myDirection11}");
運算子typeof 可以得到運算元的型別。
注意: 並非所有的字串值都會轉換為一個 orientation 值。 如果傳送的值不能轉換為列舉值中的一個,就會產生錯誤。與C# 中的其他值一樣,這些值是區分大小寫的, 所以如果字串與一個值相同,但大小寫不同(例如,將myString 設定為 North 而不是 north),就會產生錯誤。
C++中的列舉和C#的列舉的區別
在C++中的列舉常量的值不可以重複, 即不可以初始化一樣的值。一個列舉常量也不可以初始化另一個列舉常量。 在c# 中可以。
在C++中允許設定部分列舉常量對應的整數常量值, 但是要求從左到右依次設定列舉常量對應的整數常量值,並且不能重複。 在C#中可以。
在C++中,輸出值時可以直接引用列舉常量名稱, 但是C#中不可以,必須新增 “ 列舉.列舉常量名稱 ”。
其實還要很多區別,這裡就不寫了,自己慢慢發現把。