C# 入門指南

單元 9 - 列舉與結構

~~學習進度表~~

列舉 (enumeration) 與結構 (structure) 都是實值型態 (value type) ,列舉用關鍵字 (keyword) enum 宣告,結構則是用關鍵字 struct 定義

enum, struct

列舉是一組用識別字定義的整數常數,宣告定義如下

enum Day {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

這樣 Day 就會是列舉,裡頭的 Sun 等同於整數 0 ,之後逐次遞增 1Mon 等同於整數 1Tue 等同於整數 2 ,餘下可類推。

至於實際使用列舉,需要進行型態轉換,例如

using System;

namespace EnumDemo01
{
    class Program
    {
        enum Day {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

        static void Main(string[] args)
        {
            int a = (int) Day.Sun;
            int b = (int) Day.Thu;
            Console.WriteLine("Sunday: {0}", a);
            Console.WriteLine("Thursday: {0}", b);
        }
    }
}

//《程式語言教學誌》的範例程式
// http://kaiching.org/
// 專案:EnumDemo01
// 檔名:Program.cs
// 功能:示範 C# 的列舉
// 作者:張凱慶

這裡從列舉 Day 中取出 SunThu ,然後把這兩個印出來,注意取出必須加上小括弧及型態名稱,進行強制型態轉換

int a = (int) Day.Sun;
int b = (int) Day.Thu;
Console.WriteLine("Sunday: {0}", a);
Console.WriteLine("Thursday: {0}", b);

強制型態轉換是一種型態轉換的手法,用以解決型態不相容的問題。

此例執行結果如下

C:\EnumDemo01> dotnet run
Sunday: 0
Thursday: 4
C:\EnumDemo01>

列舉中的常數可以是任何的整數型態,預設是 int ,其他都要宣告,例如

enum Range: long {Max=2000000000L, Min=1000000000L};

以上將列舉裡面的常數宣告為 long ,同時直接用指派運算子設定整數值,注意整數字面常數 (literal) 最後面的 L 表示這是 long 型態。

以下程式取出 Range 的兩個常數,然後印出來

using System;

namespace EnumDemo02
{
    class Program
    {
        enum Range: long {Max=2000000000L, Min=1000000000L};

        static void Main(string[] args)
        {
            long a = (long) Range.Max;
            long b = (long) Range.Min;
            Console.WriteLine("Max: {0}", a);
            Console.WriteLine("Min: {0}", b);
        }
    }
}

//《程式語言教學誌》的範例程式
// http://kaiching.org/
// 專案:EnumDemo02
// 檔名:Program.cs
// 功能:示範 C# 的列舉
// 作者:張凱慶

執行結果如下

C:\EnumDemo02> dotnet run
Max: 2000000000
Min: 1000000000
C:\EnumDemo02>

列舉通常會用在需要常數識別字的地方,結構則是簡單的類別 (class) ,例如

using System;

namespace StructDemo01
{
    public struct Point1
    {
        public int x, y;
    }

    public struct Point2
    {
        public int x, y;

        public Point2(int p1, int p2)
        {
            x = p1;
            y = p2;
        }

        public void PrintCoordinate()
        {
            Console.WriteLine("({0}, {1})", x, y);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Point1 p1;
            p1.x = 10;
            p1.y = 2;
            Console.WriteLine("p1: ({0}, {1})", p1.x, p1.y);
            
            Point2 p2 = new Point2(11, 22);
            p2.PrintCoordinate();
            Console.WriteLine("p2: ({0}, {1})", p2.x, p2.y);
        }
    }
}

//《程式語言教學誌》的範例程式
// http://kaiching.org/
// 專案:StructDemo01
// 檔名:Program.cs
// 功能:示範 C# 的結構
// 作者:張凱慶

這裡定義了兩個結構,首先是 Point1

public struct Point1
{
    public int x, y;
}

定義結構使用關鍵字 struct ,裡頭簡單宣告兩個欄位 (field) xy ,注意 public 是宣告存取權限, public 是最寬鬆的存取層級,這讓底下 Program 類別可以使用 Point1 。執行部分在 ProgramMain() 中,先看到 Point1 的部分

Point1 p1;
p1.x = 10;
p1.y = 2;
Console.WriteLine("p1: ({0}, {1})", p1.x, p1.y);

這裡宣告了 Point1 的變數 p1 ,然後直接用指派運算子設定 xy 兩個欄位,然後印出欄位值。

第二個結構 Point2 除了兩個 xy 欄位之外,另外定義建構子 (constructor) 與 PrintCoordinate() 方法 (method)

public struct Point2
{
    public int x, y;

    public Point2(int p1, int p2)
    {
        x = p1;
        y = p2;
    }

    public void PrintCoordinate()
    {
        Console.WriteLine("({0}, {1})", x, y);
    }
}

建構子就是建立結構時所執行的特殊方法,注意建構子跟結構名稱同名,小括弧為參數列 (parameter list) ,然後不需要回傳值 (return value)

public Point2(int p1, int p2)
{
    x = p1;
    y = p2;
}

「建構子」在 C# 官方文件由機器翻譯成「建構函式」,「建構函式」是沿用 C++ 的翻譯詞彙,問題是 C# 直接定義類別,並無函式(或稱函數,原文皆為 function )的定義,因此本書採用物件導向程式設計常用的翻譯詞「建構子」。

因為建構子是直接建立物件實體的特殊方法,因此建構子不需要回傳值。

PrintCoordinate() 沒有回傳值,宣告為 void ,參數列留空

public void PrintCoordinate()
{
    Console.WriteLine("({0}, {1})", x, y);
}

參數列就是實際呼叫建構子或方法提供的參數 (parameter) ,如此例的建構子用參數設定欄位值

Point2 p2 = new Point2(11, 22);
p2.PrintCoordinate();
Console.WriteLine("p2: ({0}, {1})", p2.x, p2.y);

執行結果如下

C:\StructDemo01> dotnet run
p1: (10, 2)
(11, 22)
p2: (11, 22)
C:\StructDemo01>

結構只是簡單的類別,並不具有類別的完整功能,下一單元開始討論如何設計類別。

相關教學影片

上一頁 單元 8 - 陣列與字串
回 C# 入門指南首頁
下一頁 單元 10 - 類別
回 C# 教材首頁
回程式語言教材首頁
中英文術語對照
類別class
建構子constructor
列舉enumeration
欄位field
關鍵字keyword
字面常數literal
方法method
參數parameter
參數列parameter list
回傳值return value
結構structure
實值型態value type
參考資料
1. C# 語言教學課程 | Microsoft Docs - 列舉
2. C# 語言教學課程 | Microsoft Docs - 結構
3. C# 參考 | Microsoft Docs - enum
4. C# 參考 | Microsoft Docs - struct
5. C# 程式設計手冊 | Microsoft Docs - 使用結構
重點整理
1. 列舉是一組用識別字定義的整數常數,實際使用需要做強制型態轉換。
2. 結構則是簡單的類別,同樣可以定義欄位及方法。
問題與討論
1. 想一想,列舉的好處在哪裡?可以用在什麼地方?
2. 結構跟類別有不同?
練習
1. 建立一個新專案 Exercise0901 ,利用列舉及 DateTime 物件的 DayOfWeek 屬性判斷今天是星期幾?
2. 建立一個新專案 Exercise0902 ,寫一個結構記錄商品名稱、售價、成本,然後印在命令列上。