06.01.2015 Views

第一章C#語言基礎

第一章C#語言基礎

第一章C#語言基礎

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

第 一 章 C# 語 言 基 礎<br />

本 章 介 紹 C# 語 言 的 基 礎 知 識 , 希 望 具 有 C 語 言 的 讀 者 能 夠 基 本 掌 握 C# 語 言 , 以 此 為 基 礎 ,<br />

能 夠 進 一 步 學 習 用 C# 語 言 編 寫 Window 應 用 程 序 和 Web 應 用 程 序 。 當 然 僅 靠 一 章 的 內 容 就 完<br />

全 掌 握 C# 語 言 是 不 可 能 的 , 如 需 進 一 步 學 習 C# 語 言 , 還 需 要 認 真 閱 讀 有 關 C# 語 言 的 專 著 。<br />

1.1 C# 語 言 特 點<br />

Microsoft.NET( 以 下 簡 稱 ·NET) 框 架 是 微 軟 提 出 的 新 一 代 Web 軟 件 開 發 模 型 ,C# 語 言 是 ·NET<br />

框 架 中 新 一 代 的 開 發 工 具 。C# 語 言 是 一 種 現 代 、 物 件 導 向 的 語 言 , 它 簡 化 了 C++ 語 言 在 類 、 命<br />

名 空 問 、 方 法 多 載 和 異 常 處 理 等 方 面 的 操 作 , 它 摒 棄 了 C++ 的 複 雜 性 , 更 易 使 用 , 更 少 出 錯 。<br />

它 使 用 組 件 編 程 , 和 VB 一 樣 容 易 使 用 。C# 語 法 和 C++ 和 JAVA 語 法 非 常 相 似 , 如 果 讀 者 用 過<br />

C++ 和 JAVA, 學 習 C# 語 言 應 是 比 較 輕 鬆 的 。<br />

用 C# 語 言 編 寫 的 源 碼 程 式 , 必 須 用 C# 語 言 編 譯 器 將 C# 源 碼 程 式 編 譯 為 中 間 語 言 (Microsoft<br />

Intermediate Language, MSIL) 代 碼 , 形 成 副 檔 名 為 exe 或 dll 文 件 。 中 間 語 言 代 碼 不 是 CPU 可 執<br />

行 的 機 器 碼 , 在 程 序 執 行 時 , 必 須 由 通 用 語 言 執 行 環 境 (Common Language Runtime,CLR) 中 的<br />

即 時 編 譯 器 (Just In Time,JIT) 將 中 間 語 言 代 碼 翻 譯 為 CPU 可 執 行 的 機 器 碼 , 由 CPU 執 行 。CLR<br />

為 C# 語 言 中 間 語 言 代 碼 執 行 提 供 了 一 種 執 行 時 環 境 ,C# 語 言 的 CLR 和 JAVA 語 言 的 虛 擬 機 類<br />

似 。 這 種 執 行 方 法 使 執 行 速 度 變 慢 , 但 帶 來 其 它 一 些 好 處 , 主 要 有 :<br />

通 用 語 言 規 範 (Common Language Specification,CLS):.NET 系 統 包 括 如 下 語 言 :C#、C++、<br />

VB、J#, 他 們 都 遵 守 通 用 語 言 規 範 。 任 何 遵 守 通 用 語 言 規 範 的 語 言 源 程 序 , 都 可 編 譯 為 相<br />

同 的 中 間 語 言 代 碼 , 由 CLR 負 責 執 行 。 只 要 為 其 它 操 作 系 統 編 製 相 應 的 CLR, 中 問 語 言 代<br />

碼 也 可 在 其 它 系 統 中 執 行 。<br />

自 動 記 憶 體 管 理 :CLR 內 建 垃 圾 收 集 器 , 當 變 數 實 例 的 生 命 周 期 結 束 時 , 垃 圾 收 集 器 負 責<br />

收 回 不 被 使 用 的 實 例 佔 用 的 記 憶 體 空 間 。 不 必 像 C 和 C++ 語 言 , 用 語 句 在 堆 積 中 建 立 的 實<br />

例 , 必 須 用 語 句 釋 放 實 例 佔 用 的 記 憶 體 空 間 。 也 就 是 說 ,CLR 具 有 自 動 記 憶 體 管 理 功 能 。<br />

跨 語 言 處 理 : 由 於 任 何 遵 守 通 用 語 言 規 範 的 語 言 源 程 序 都 可 編 譯 為 相 同 的 中 間 語 言 代 碼 ,<br />

不 同 語 言 設 計 的 組 件 , 可 以 互 相 通 用 , 可 以 從 其 它 語 言 定 義 的 類 衍 生 出 本 語 言 的 新 類 。 由<br />

於 中 間 語 言 代 碼 由 CLR 負 責 執 行 , 因 此 異 常 處 理 方 法 是 一 致 的 , 這 在 調 試 一 種 語 言 調 用 另<br />

一 種 語 言 的 子 程 序 時 , 顯 得 特 別 方 便 。<br />

增 加 安 全 :C# 語 言 不 支 援 指 標 , 一 切 對 記 憶 體 的 存 取 者 都 必 須 通 過 物 件 的 參 照 變 數 來 實<br />

現 , 只 允 許 存 取 記 憶 體 中 允 許 存 取 的 部 分 , 這 就 防 止 病 毒 程 序 使 用 非 法 指 標 存 取 私 有 成<br />

員 。 也 避 免 指 標 的 誤 操 作 產 生 的 錯 誤 。CLR 執 行 中 間 語 言 代 碼 需 要 對 中 間 語 言 代 碼 的 安 全<br />

性 、 完 整 性 進 行 驗 證 , 防 止 病 毒 對 中 間 語 言 代 碼 的 修 改 。<br />

版 本 支 援 : 系 統 中 的 組 件 或 動 態 聯 接 庫 可 能 要 升 級 , 由 於 這 些 組 件 或 動 態 聯 接 庫 都 要 在 註<br />

冊 表 中 註 冊 , 由 此 可 能 帶 來 一 系 列 問 題 , 例 如 , 安 裝 新 程 序 時 自 動 安 裝 新 組 件 替 換 舊 組 件 ,<br />

有 可 能 使 某 些 必 須 使 用 舊 組 件 才 可 以 執 行 的 程 序 , 使 用 新 組 件 執 行 不 了 。 在 .NET 中 這 些 組<br />

1


。//<br />

件 或 動 態 聯 接 庫 不 必 在 註 冊 表 中 註 冊 , 每 個 程 序 都 可 以 使 用 自 帶 的 組 件 或 動 態 聯 接 庫 , 只<br />

要 把 這 些 組 件 或 動 態 聯 接 庫 放 到 執 行 程 序 所 在 文 件 夾 的 子 文 件 夾 bin 中 , 執 行 程 序 就 自 動<br />

使 用 在 bin 文 件 夾 中 的 組 件 或 動 態 聯 接 庫 。 由 於 不 需 要 在 註 冊 表 中 註 冊 , 軟 件 的 安 裝 也 變<br />

得 容 易 了 , 一 般 將 執 行 程 序 及 庫 文 件 拷 貝 到 指 定 文 件 夾 中 就 可 以 了 。<br />

完 全 物 件 導 向 : 不 像 C++ 語 言 , 暨 支 援 程 序 導 向 程 序 設 計 , 又 支 援 物 件 導 件 程 序 設 計 ,C#<br />

語 言 是 完 全 物 件 導 向 的 , 在 C# 中 不 再 存 在 全 域 函 數 、 全 域 變 數 , 所 有 的 函 數 、 變 數 和 常 數<br />

部 必 須 定 義 在 類 中 , 避 免 了 命 名 衝 突 。C# 語 言 不 支 援 多 重 繼 承 。<br />

1.2 編 寫 主 控 台 應 用 程 序<br />

1.2.1 使 用 SDK 命 令 列 工 具 編 寫 主 控 台 程 序<br />

第 一 個 程 式 總 是 非 常 簡 單 的 , 程 序 首 先 讓 用 戶 通 過 鍵 盤 輸 入 自 己 的 名 字 , 然 後 程 式 在 螢 幕<br />

上 印 出 一 條 歡 迎 訊 息 , 程 式 碼 是 這 樣 的 :<br />

命 名 空 間 入<br />

using System; // C# 語 言 加 註 解 方 法 , 註 解 到 本 行 結 束 定 義 , 類 的 概 念 見 下 一 節 為 導<br />

class Welcome //<br />

解 開 始 , 言 註 解 用 法 相 同 類<br />

{ /*<br />

*/ 解 結 束 註 註<br />

}<br />

C 語 和<br />

static void Main() // 程 序 , 程 序 入 口 函 數 , 必 須 在 一 個 類 中 定 義 主<br />

{<br />

}<br />

Console.WriteLine(" :"); //<br />

Enter<br />

的 姓 名 主 控 台 輸 出 字 串 鍵 盤 讀 入 資 料 , 鍵 入 束 你 入 鍵 請<br />

Console.ReadLine(); //<br />

!"); 迎 從<br />

Console.WriteLine(" 歡<br />

結<br />

可 以 用 任 意 一 種 文 字 編 輯 軟 件 完 成 上 述 程 式 碼 的 編 寫 , 然 後 把 文 件 存 檔 , 假 設 文 件 名 叫 做<br />

welcome.cs,C# 源 碼 檔 案 是 以 cs 作 為 文 件 的 副 檔 名 。 和 C 語 言 相 同 ,C# 語 言 是 區 分 大 小 寫 的 。<br />

高 級 語 言 總 是 依 賴 於 許 多 在 程 式 外 部 預 定 義 的 變 數 和 函 數 。 在 C 成 C++ 中 這 些 定 義 一 般 放 到 頭<br />

文 件 中 , 用 #include 語 句 來 導 入 這 個 標 頭 檔 , 而 在 C# 語 言 中 使 用 using 語 句 導 入 命 名 空 間 ,using<br />

System 語 句 意 義 是 導 入 System 命 名 空 間 ,C# 中 的 using 語 句 的 用 途 與 C++ 中 的 #include 語 句 的<br />

用 途 基 本 類 似 , 用 於 導 入 預 定 義 的 變 數 和 函 數 , 這 樣 在 自 己 的 程 式 中 就 可 以 自 由 地 使 用 這 些 變<br />

數 和 函 數 。 如 果 沒 有 導 入 命 名 空 間 的 話 , 我 們 該 怎 麼 辦 呢 程 序 還 能 保 持 正 確 嗎 答 案 是 肯 定<br />

的 , 那 樣 的 話 , 我 們 就 必 須 把 程 式 碼 改 寫 成 下 面 的 樣 子 :<br />

class Welcome<br />

{<br />

static void Main()<br />

{<br />

2


}<br />

}<br />

System.Console.WriteLine(" :"); 入 你 的 姓 名 鍵 請<br />

System.Console.ReadLine();<br />

System.Console.WriteLine(" 歡<br />

!");<br />

也 就 是 在 每 個 Console 前 加 上 一 個 前 綴 System, 這 個 小 圓 點 表 示 Console 是 作 為 System 的 成 員<br />

迎<br />

而 存 在 的 。C# 中 拋 棄 了 C 和 C++ 中 繁 雜 且 極 易 出 錯 的 運 算 子 , 如 :: 和 -> 等 ,C# 中 的 複 合<br />

名 字 一 律 通 過 · 來 連 接 。System 是 .Net 平 台 框 架 提 供 的 最 基 本 的 命 名 空 間 之 一 , 有 關 命 名<br />

空 間 的 詳 細 使 用 方 法 將 在 以 後 詳 細 介 紹 , 這 裡 只 要 學 會 怎 樣 導 入 命 名 空 間 就 足 夠 了 。<br />

程 序 的 第 二 行 宣 告 了 一 個 類 , 類 的 名 字 叫 做 Welcome。C# 程 序 中 每 個 變 數 或 函 數 都 必 須 屬<br />

於 一 個 類 , 包 括 主 函 數 Main(), 不 能 像 C 或 C++ 那 樣 建 立 全 域 變 數 。C# 語 言 程 序 總 是 從 Main()<br />

方 法 開 始 執 行 , 一 個 程 序 中 不 允 許 出 現 兩 個 或 兩 行 以 上 的 Main() 方 法 。 請 牢 記 C# 中 Main() 方<br />

法 必 須 被 包 含 在 一 個 類 中 ,Main 的 第 一 個 字 母 必 須 大 寫 , 必 須 是 一 個 靜 態 方 法 , 也 就 是 Main()<br />

方 法 必 須 使 用 static 修 飾 。static void Main() 是 類 Welcome 中 定 義 的 主 函 數 , 靜 態 方 法 意 義 見 以<br />

後 章 節 。<br />

程 序 所 進 行 的 輸 入 輸 出 功 能 是 通 過 Console 類 來 完 成 的 ,Console 類 是 在 命 名 空 間 System<br />

中 已 經 定 義 好 的 一 個 類 。Console 有 兩 個 最 基 本 的 方 法 WriteLine 和 ReadLine。ReadLine 表 示 從<br />

輸 入 設 備 輸 入 資 料 ,WriteLine 則 用 於 在 輸 出 設 備 上 輸 出 資 料 。<br />

如 果 在 電 腦 上 安 裝 了 Visual Studio.Net, 則 可 以 在 集 成 開 發 環 境 中 直 接 選 擇 快 捷 鍵 或 選 單<br />

命 令 編 譯 並 執 行 源 文 件 。 如 果 您 不 具 備 這 個 條 件 , 那 麼 至 少 需 要 安 裝 Microsoft.Net 這 樣 才 能<br />

夠 執 行 C# 語 言 程 序 。Microsoft.Net Framework SDK 中 內 置 了 C# 的 編 譯 器 csc.exe, 下 面 讓 我 們<br />

使 用 這 個 微 軟 提 供 的 命 令 列 編 譯 器 時 對 程 序 welcome.cs 進 行 編 譯 。 假 設 已 經 將 文 件 保 存 在<br />

d:\Csharp 目 錄 下 , 啟 功 命 令 列 提 示 符 , 在 螢 幕 上 輸 入 一 行 命 令 : d: 鍵 入 Enter, 鍵 入 命 令 :<br />

C:\Windows\Microsoft.Net\Framework\v3.5\csc welcome.cs<br />

如 果 一 切 正 常 welcome.cs 文 件 將 被 編 譯 , 編 譯 後 產 生 可 執 行 文 件 Welcome.exe。 可 以 在 命<br />

令 提 示 符 視 窗 執 行 可 執 行 檔 Welcome.exe, 螢 幕 上 出 現 一 行 文 字 提 示 您 輸 入 姓 名 : 請 鍵 入 你 的<br />

姓 名 , 輸 入 任 意 文 字 並 按 下 Enter 鍵 , 螢 幕 上 印 出 歡 迎 訊 息 : 歡 迎 !<br />

注 意 , 和 我 們 使 用 過 的 絕 大 多 數 編 譯 器 不 同 , 在 C# 中 編 譯 器 只 執 行 編 譯 這 個 過 程 , 而 在 C<br />

和 C++ 中 要 經 過 編 譯 和 鏈 接 兩 個 階 段 。 換 言 之 C# 源 碼 檔 並 不 被 編 譯 為 目 標 檔 .obj, 而 是 直 接 產<br />

生 成 可 執 行 文 件 .exe 或 動 態 鏈 接 庫 .dll,C# 編 譯 器 中 不 需 要 包 含 鏈 接 器 。<br />

1.2.1 使 用 Visual Studio.Net 建 立 主 控 台 程 序<br />

(1) 執 行 Visual Studio.Net 程 序 , 出 現 如 圖 1.2.2A 界 面 。<br />

(2) 單 擊 新 建 專 案 按 鈕 , 出 現 如 圖 1.2.2B 對 話 框 。 在 專 案 類 型 (P) 編 輯 框 中 選 擇 Visual C#, 在 範<br />

本 (T) 編 輯 框 中 選 擇 主 控 制 台 應 用 程 序 , 名 稱 (N) 編 輯 框 中 鍵 入 e1, 在 位 置 (L) 編 輯 框 中 鍵 入<br />

D:\Csharp, 必 須 預 先 產 生 文 件 夾 D:\Csharp。 也 可 以 單 擊 瀏 覽 按 鈕 , 在 打 開 文 件 對 話 框 中 選<br />

擇 文 件 夾 , 單 擊 確 定 按 鈕 , 產 生 專 案 。 出 現 如 圖 1.2.2C 界 面 。 編 寫 一 行 應 用 程 序 , 可 能 包<br />

3


含 多 個 文 件 , 才 能 生 成 可 執 行 文 件 , 所 有 這 些 文 件 的 集 合 叫 做 一 個 專 案 。<br />

(3) 修 改 e1.cs 文 件 如 下 , 有 陰 影 部 分 是 新 增 加 的 語 句 , 其 餘 是 集 成 環 境 自 動 生 成 的 。<br />

using System;<br />

using System.Collections.Generic;<br />

using System.Linq;<br />

using System.Text;<br />

namespace e1<br />

{<br />

class Program<br />

{<br />

static void Main(string[] args)<br />

{<br />

Console.WriteLine(" :"); 入 你 的 姓 名 鍵 請<br />

System.Console.ReadLine();<br />

System.Console.WriteLine(" 歡<br />

System.Console.Read();<br />

!"); 迎<br />

4


:{0},<br />

}<br />

}<br />

}<br />

(4) 按 CTRL+F5 鍵 , 執 行 程 序 , 如 右 圖 , 與 第 1.2.1 節 執 行 效 果 相 同 。 螢 幕 上 出 現 一 行 文 字 ,<br />

提 示 你 輸 入 姓 名 , 請 鍵 入 你 的 姓 , 輸 入 任 意 字 元 並 按 下 Enter 鍵 , 螢 幕 將 印 出 歡 迎 訊 息 :<br />

歡 迎 ! 鍵 入 Enter 退 出 程 序 。<br />

1.3 類 的 基 本 概 念<br />

C# 語 言 是 一 種 現 代 、 物 件 導 向 的 語 言 , 物 件 導 向 對 程 序 設 計 方 法 提 出 了 一 個 全 新 的 慨 念 ,·<br />

它 的 主 要 思 想 是 將 資 料 ( 資 料 成 員 ) 及 處 理 這 些 資 料 的 相 應 方 法 ( 函 數 成 員 ) 封 裝 到 類 中 , 類 的 實<br />

例 則 稱 為 對 象 或 物 件 (object), 這 就 是 我 們 常 說 的 封 裝 性 。<br />

1.3.1 類 的 基 本 概 念<br />

類 可 以 認 為 是 對 結 構 的 擴 充 , 它 和 C 中 的 結 構 最 大 的 不 同 是 : 類 中 不 但 可 以 包 括 資 料 , 還<br />

包 括 處 理 這 些 資 料 的 函 數 。 類 是 對 資 料 和 處 理 資 料 的 方 法 ( 函 數 ) 的 封 裝 。 類 是 對 某 一 類 具 有 相<br />

同 特 性 和 行 為 的 事 物 的 描 述 。 例 如 , 定 義 一 個 描 述 個 人 情 況 的 類 Person 如 下 :<br />

using System;<br />

class Person // ,class ,Person 義 是 保 留 字 , 表 示 定 義 一 個 類 是 類 名 定 的 類<br />

{<br />

}<br />

private string name = " 張<br />

private int age = 12; //private<br />

( 方 法 的 表<br />

public void Display() // 類<br />

{<br />

}<br />

"; // 類 的 資 料 成 員 宣 告 示 私 有 資 料 成 員 三<br />

函<br />

) 宣 告 , 顯 示 姓 名 和 年 齡 數<br />

Console.WriteLine(" :{1}", name, age); 齡 年 名 姓<br />

public void SetName(string PersonName) // 改 姓 名 為 方 修<br />

{<br />

}<br />

name = PersonName;<br />

public void setAge(int PersonAge)<br />

{<br />

}<br />

age = PersonAge;<br />

Console.WriteLine(" 姓 名 :{0}, 年 齡 :{1}", name, age) 的 意 義 是 將 第 二 個 參 數 變 數 name 變 為 字<br />

( 函 法<br />

) 數<br />

5


串 填 到 {0} 位 置 , 將 第 三 個 參 數 變 數 age 變 為 字 串 填 到 {1} 位 置 , 將 第 一 個 參 數 表 示 的 字 串 在 顯<br />

示 器 上 輸 出 。<br />

大 家 注 意 , 這 裡 我 們 實 際 定 義 了 一 個 新 的 資 料 型 別 , 為 用 戶 自 己 定 義 的 資 料 型 別 , 是 對 個<br />

人 的 特 性 和 行 為 的 描 述 , 型 別 名 為 Person, 它 和 int、char 等 一 樣 , 為 一 種 資 料 型 別 。 用 定 義<br />

新 資 料 型 別 Person 類 的 方 法 把 資 料 和 處 理 資 料 的 函 數 封 裝 起 來 。 類 的 宣 告 格 式 如 下 :<br />

屬 性 類 修 飾 字 class 類 名 { 類 體 }<br />

其 中 , 關 鍵 字 class、 類 名 和 類 體 是 必 須 的 , 其 它 項 是 可 選 項 , 類 修 飾 字 包 括 new、public、<br />

protected、internal、private、abstract 和 sealed, 這 些 類 修 飾 字 以 後 介 紹 , 類 體 用 於 定 義 類 的<br />

成 員 。<br />

1.3.2 類 成 員 的 存 取 控 制<br />

一 般 希 望 類 中 一 些 資 料 不 被 隨 意 修 改 , 只 能 按 指 定 方 法 修 改 , 既 隱 蔽 一 些 資 料 , 同 時 這 些<br />

函 數 也 不 希 望 被 其 它 類 程 序 調 用 , 只 能 在 類 內 部 使 用 。 如 何 解 決 這 個 問 題 呢 可 用 存 取 權 限 控<br />

制 字 , 常 用 的 存 取 權 限 控 制 字 如 下 :private( 私 有 )、public( 公 有 )。 在 資 料 成 員 或 函 數 成 員 前 增<br />

加 存 取 權 限 控 制 字 , 可 以 指 定 該 資 料 成 員 或 函 數 成 員 的 存 取 權 限 。<br />

私 有 資 料 成 員 只 能 被 類 內 部 的 函 數 使 用 和 修 改 , 私 有 函 數 成 員 只 能 被 類 內 部 的 其 它 函 數 調<br />

用 。 類 的 公 有 函 數 成 員 可 以 被 類 的 外 部 程 序 調 用 , 類 的 公 有 資 料 成 員 可 以 被 類 的 外 部 程 序 直 接<br />

使 用 修 改 。 公 有 函 數 實 際 是 一 個 類 和 外 部 通 訊 的 介 面 , 外 部 函 數 通 過 調 用 公 有 函 數 , 按 照 預 先<br />

設 定 好 的 方 法 修 改 類 的 私 有 成 員 。 對 於 上 述 例 子 ,name 和 age 是 私 有 資 料 成 員 , 只 能 通 過 公<br />

有 函 數 SetName() 和 SetAge() 修 改 , 即 它 們 只 能 按 指 定 方 法 修 改 。<br />

這 裡 再 一 次 解 釋 一 下 封 裝 , 它 有 兩 個 意 義 , 第 一 是 把 資 料 和 處 理 資 料 的 方 法 同 時 定 義 在 類<br />

中 。 第 二 是 用 存 取 權 限 控 制 字 使 資 料 隱 蔽 。<br />

1.3.3 類 的 對 象<br />

Person 類 僅 是 一 個 用 戶 新 定 義 的 資 料 型 別 , 由 它 可 以 生 成 Person 類 的 實 例 ,C# 語 言 叫 對<br />

象 ( 或 翻 譯 為 物 件 )。 用 如 下 方 法 宣 告 類 的 對 象 :Person OnePerson=new Person();, 此 語 句 的 意<br />

義 是 建 立 Person 類 對 象 , 返 回 對 象 地 址 指 派 給 Person 類 變 數 OnePerson。 也 可 以 分 兩 步 產<br />

生 Person 類 的 對 象 :Person OnePerson;OnePerson = new Person();OnePerson 雖 然 儲 存 的 是<br />

Person 類 對 象 地 址 , 但 不 是 C 中 的 指 標 , 不 能 像 指 標 那 樣 可 以 進 行 加 減 運 算 , 也 不 能 轉 換 為<br />

其 它 型 別 地 址 , 它 是 參 照 型 別 變 數 , 只 能 參 照 ( 引 用 )Person 對 象 , 具 體 意 義 參 見 以 後 章 節 。 和<br />

C、C++ 不 同 ,C# 只 能 用 此 種 方 法 生 成 類 對 象 。<br />

在 程 序 中 , 可 以 用 「OnePerson. 方 法 名 」 或 「OnePerson. 資 料 成 員 名 」 存 取 對 象 的 成 員 。<br />

例 如 :OnePerson.Display(), 公 用 資 料 成 員 也 可 以 這 樣 存 取 。 注 意 ,C# 語 言 中 不 包 括 C++ 語 言<br />

中 的 -> 符 號 。<br />

6


1.3.4 類 的 建 構 函 數 和 解 構 函 數<br />

在 建 立 類 的 對 象 時 , 需 做 一 些 初 始 化 工 作 , 例 如 對 資 料 成 員 初 始 化 。 這 些 可 以 用 建 構 函 數<br />

來 完 成 。 每 當 用 new 生 成 類 的 對 象 時 , 自 動 調 用 類 的 建 構 函 數 。 因 此 , 可 以 把 初 始 化 的 工 作<br />

放 到 建 構 函 數 中 完 成 。 建 構 函 數 和 類 名 相 同 , 沒 有 返 回 值 。 例 如 可 以 定 義 Person 類 的 建 構 函<br />

數 如 下 :<br />

建 構 函 數 , 函 數 名 和 類 同 名 , 無 返 回 值 的<br />

// 類<br />

public Person(string Name, int Age)<br />

。<br />

{<br />

}<br />

name = Name;<br />

age = Age;<br />

當 用 Person OnePerson=new Person(" 張 五 ",20) 語 句 生 成 Person 類 對 象 時 , 將 自 動 調 用<br />

以 上 建 構 函 數 。 請 注 意 如 何 把 參 數 傳 遞 給 建 構 函 數 。<br />

變 數 和 類 的 對 象 都 有 生 命 期 , 生 命 期 結 束 , 這 些 變 數 和 對 象 就 要 被 撤 銷 。 類 的 對 象 被 撤 銷<br />

時 , 將 自 動 調 用 解 構 函 數 。 一 些 善 後 工 作 可 放 在 解 構 函 數 中 完 成 。 解 構 函 數 的 名 字 為 「~ 類 名 」,<br />

無 返 回 型 別 , 也 無 參 數 。Person 類 的 解 構 函 數 為 ~Person()。C# 中 類 解 構 函 數 不 能 顯 式 地 被 調<br />

用 , 它 是 被 垃 圾 收 集 器 撤 銷 不 被 使 用 的 對 象 時 自 動 調 用 的 。<br />

1.3.5 類 的 建 構 函 數 的 多 載<br />

在 C# 語 言 中 , 同 一 個 類 中 的 函 數 , 如 果 函 數 名 相 同 , 而 參 數 型 別 或 個 數 不 同 , 認 為 是 不<br />

同 的 函 數 , 這 叫 函 數 多 載 。 僅 返 回 值 不 同 , 不 能 看 作 不 同 的 函 數 。 這 樣 , 可 以 在 類 定 義 中 , 定<br />

義 多 個 建 構 函 數 , 名 字 相 同 , 參 數 型 別 或 個 數 不 同 。 根 據 生 成 類 的 對 象 方 法 不 同 , 調 用 不 同 的<br />

建 構 函 數 。 例 如 可 以 定 義 Person 類 沒 有 參 數 的 建 構 函 數 如 下 :<br />

建 構 函 數 , 函 數 名 和 類 同 名 , 無 返 回 型 別 。 的<br />

// 類<br />

public Person()<br />

{<br />

}<br />

name = " 張<br />

";<br />

age = 12;<br />

三<br />

用 語 句 Person OnePerson=new Person(" 李 四 ", 30) 生 成 對 象 時 , 將 調 用 有 參 數 的 建 構 函 數 ,<br />

而 用 語 句 Person OnePerson=new Person() 生 成 對 象 時 , 調 用 無 參 數 的 建 構 函 數 。 由 於 解 構 函 數<br />

無 參 數 , 因 此 , 解 構 函 數 不 能 多 載 。<br />

7


1.3.6 使 用 Person 類 的 完 整 的 例 子<br />

下 邊 用 一 個 完 整 的 例 子 說 明 Person 類 的 使 用 :(VisualStudio.Net 編 譯 通 過 )<br />

using System;<br />

namespace e1 // 義 以 下 程 式 碼 所 屬 命 名 空 間 , 意 義 見 以 後 章 節 定<br />

{<br />

class Person<br />

{<br />

private String name = " 張<br />

private int age = 12;<br />

) 數 告 , 顯 示 姓 名 和 年 齡 方 的<br />

// 類<br />

( 函 法<br />

public void Display()<br />

{<br />

}<br />

宣<br />

Console.WriteLine(" 姓<br />

// ( 修 改 姓 名 的 方 法 函 定 指<br />

";// 類 的 資 料 成 員 宣 告 三<br />

: {0}, 年 名<br />

)<br />

public void SetName(string PersonName)<br />

數<br />

{<br />

}<br />

name = PersonName;<br />

// 定 修 改 年 齡 的 方 指<br />

( 函 法<br />

) 數<br />

public void SetAge(int PersonAge)<br />

{<br />

}<br />

age = PersonAge;<br />

// , 函 數 函 數 名 和 類 同 構 建<br />

, 無 名<br />

public Person(string Name, int Age)<br />

值 回 返<br />

{<br />

}<br />

name = Name;<br />

age = Age;<br />

// 的 建 構 函 數 多 類<br />

public Person()<br />

載<br />

{<br />

}<br />

name = " 田<br />

age = 12;<br />

"; 七<br />

:{1}", name, age); 齡<br />

8


類<br />

}<br />

}<br />

class Class1<br />

{<br />

}<br />

static void Main(string[] args)<br />

{<br />

}<br />

Person OnePerson = new Person(" 李<br />

OnePerson.Display();<br />

(Class1 誤 , 在 其 它 類 錯 句<br />

/*<br />

不 能 直 接 修 下<br />

Person 類 改<br />

),<br />

中 的 私 有 成 員 中<br />

//OnePerson.name = " ";<br />

Person 能 通 過 中 公 有 方 五 王<br />

/*<br />

修 只<br />

Person 類 改<br />

中 的 私 有 成 類<br />

OnePerson.SetName(" 王<br />

OnePerson.SetAge(40);<br />

OnePerson.Display();<br />

。*/<br />

SetName 法<br />

name。*/<br />

"); 五 員<br />

OnePerson = new Person();<br />

OnePerson.Display();<br />

鍵 入 CTRL+F5 執 行 後 , 顯 示 的 效 果 是 :<br />

姓 名 : 李 四 , 年 齡 :30<br />

姓 名 : 王 五 , 年 齡 :40<br />

姓 名 : 田 七 , 年 齡 :12<br />

", 30); // 生 成 類 的 對 象 四<br />

1.4 C# 的 資 料 型 別<br />

從 大 的 方 面 來 分 ,C# 語 言 的 資 料 型 別 可 以 分 為 三 種 : 實 值 型 別 、 參 照 型 別 、 指 標 (pointer)<br />

型 別 , 指 標 型 別 僅 用 於 非 安 全 程 式 碼 中 。 本 節 重 點 討 論 實 值 型 別 和 參 照 型 別 。<br />

1.4.1 實 值 型 別 和 參 照 型 別 區 別<br />

在 C# 語 言 中 , 實 值 型 別 變 數 儲 存 的 是 資 料 型 別 所 代 表 的 實 際 資 料 , 實 值 型 別 變 數 的 值 ( 或<br />

實 例 ) 儲 存 在 堆 疊 (Stack) 中 , 指 派 語 句 是 傳 遞 變 數 的 值 。 參 照 型 別 ( 例 如 類 就 是 參 照 型 別 ) 的 實<br />

例 , 也 稱 為 對 象 , 不 存 在 堆 疊 中 , 而 儲 存 在 受 管 的 堆 積 (Managed Heap) 中 , 堆 積 實 際 上 是 計 算<br />

機 系 統 中 的 空 閒 記 憶 體 。 參 照 型 別 變 數 的 值 儲 存 在 堆 疊 中 , 但 儲 存 的 不 是 參 照 型 別 對 象 , 而 是<br />

儲 存 參 照 型 別 對 象 的 參 照 ( 地 址 ), 和 指 標 所 代 表 的 地 址 不 同 , 參 照 所 代 表 的 地 址 不 能 被 修 改 ,<br />

9


將<br />

和<br />

為<br />

中<br />

也 不 能 轉 換 為 其 它 型 別 地 址 , 它 是 參 照 型 別 變 數 , 只 能 參 照 指 定 類 對 象 , 參 照 型 別 變 數 指 派 語<br />

句 是 傳 遞 對 象 的 地 址 。 見 下 例 :<br />

using System;<br />

class MyClass// 為 參 照 型 別 類<br />

{<br />

}<br />

public int a = 0;<br />

class Test<br />

{<br />

}<br />

static void Main()<br />

{<br />

}<br />

f1();<br />

static public void f1()<br />

{<br />

}<br />

int v1 = 1;// 數 v1, (Stack)<br />

v1 ( )<br />

其 值 儲 存 在 堆 疊 值 遞 變 別 型 值 實<br />

int v2 = v1;//<br />

的<br />

v2 = 2;//v2 = 2,v1 值<br />

不 變 。 傳<br />

MyClass r1 = new MyClass();//<br />

r2<br />

變 代 表 是 同 一 照 參<br />

MyClass r2 = r1;//r1<br />

語<br />

r2.a = 2;// 和<br />

都<br />

r1.a = 2 等 句<br />

v2,v2 = 1,v1 值 不 變 。 給<br />

r1 儲 數<br />

MyClass 類 個<br />

MyClass 類 對 象 的 地 址 對 象 存<br />

儲 存 在 堆 疊 中 的 變 數 , 當 其 生 命 期 結 束 , 自 動 被 撤 銷 , 例 如 ,v1 儲 存 在 堆 疊 中 ,v1 和 函<br />

價<br />

數 f1 同 生 命 期 , 退 出 函 數 f1, 此 時 v1 不 存 在 了 。 但 在 堆 積 中 的 對 象 不 能 自 動 被 撤 銷 。 因 此 C<br />

和 C++ 語 言 , 在 堆 積 中 建 立 的 對 象 , 不 使 用 時 必 須 用 語 句 釋 放 對 象 佔 用 的 儲 存 空 間 。.NET 系<br />

統 CLR 內 建 垃 圾 收 集 器 , 當 對 象 的 參 照 變 數 被 撤 銷 , 表 示 對 象 的 生 命 期 結 束 , 垃 圾 收 集 器 負<br />

責 收 回 不 被 使 用 的 對 象 佔 用 的 儲 存 空 間 。 例 如 , 上 例 中 參 照 變 數 r1 及 r2 是 MyClass 類 對 象<br />

的 參 照 , 儲 存 在 堆 疊 中 , 退 出 函 數 f1, 此 時 r1 和 r2 都 不 存 在 了 , 在 堆 積 中 的 MyClass 類 對<br />

象 也 就 被 垃 圾 收 集 器 撤 銷 。 也 就 是 說 ,CLR 具 有 自 動 記 憶 體 管 理 功 能 。<br />

1.4.2 實 值 型 別 變 數 分 類<br />

C# 語 言 實 值 型 別 可 以 分 為 以 下 幾 種 :<br />

<br />

簡 單 型 別 (Simple types)<br />

簡 單 型 別 中 包 括 : 數 值 型 別 和 布 爾 型 別 (bool)。 數 值 型 別 又 細 分 為 : 整 數 型 別 、 字 元 型 別<br />

(char)、 浮 點 數 型 別 和 十 進 制 型 別 (decimal)。<br />

<br />

結 構 型 別 (Struct types)<br />

10


用<br />

用<br />

<br />

列 舉 型 別 (Enumeration types)<br />

C# 語 言 實 值 型 別 變 數 無 論 如 何 定 義 , 總 是 實 值 型 別 變 數 , 不 會 變 為 參 照 型 別 變 數 。<br />

1.4.3 結 構 型 別<br />

結 構 型 別 和 類 一 樣 , 可 以 宣 告 建 構 函 數 、 資 料 成 員 、 方 法 、 屬 性 等 。 結 構 和 類 的 最 根 本 的<br />

區 別 是 結 構 是 實 值 型 別 , 類 是 參 照 型 別 。 和 類 不 同 , 結 構 不 能 從 另 外 一 個 結 構 或 者 類 衍 生 , 本<br />

身 也 不 能 被 繼 承 , 因 此 不 能 定 義 抽 像 結 構 , 結 構 成 員 也 不 能 被 存 取 權 限 控 制 字 protected 修 飾 ,<br />

也 不 能 用 virtual 和 abstract 修 飾 結 構 方 法 。 在 結 構 中 不 能 定 義 解 構 函 數 。 但 結 構 有 預 設 的 無<br />

參 數 建 構 函 數 。<br />

雖 然 結 構 不 能 從 類 和 結 構 衍 生 , 可 是 結 構 能 夠 繼 承 介 面 , 結 構 繼 承 介 面 的 方 法 和 類 繼 承 介<br />

面 的 方 法 基 本 一 致 。 下 面 例 子 定 義 一 個 點 結 構 point:<br />

using System;<br />

struct point// 構 定 義 結<br />

{<br />

}<br />

public int x, y;// 構 中 也 可 以 宣 告 建 構 函 結<br />

class Test<br />

{<br />

}<br />

static void Main()<br />

{<br />

} //<br />

point P1;<br />

P1.x = 166;<br />

P1.y = 111;<br />

point P2;<br />

P2 = P1;// 值<br />

point P3 = new point();//<br />

生<br />

P3 僅 數<br />

( 必 數<br />

須 有 參<br />

= 166,P2.y = 111<br />

生<br />

) 和 方 法 , 變 數 不 能 賦 初 值 數<br />

仍<br />

1.4.4 簡 單 型 別<br />

P2.x , 使 遞 傳<br />

new<br />

P3,P3 構 變 數 結 成<br />

實 值 型 別 變 數 為<br />

new<br />

成 結 構 變<br />

示 調 用 預 設 的 建 構 函 數 , 使 x=y=0。 表<br />

11<br />

簡 單 型 別 也 是 結 構 型 別 , 因 此 有 建 構 函 數 、 資 料 成 員 、 方 法 、 屬 性 等 , 因 此 下 列 語 句 int i<br />

= int.MaxValue; string s = i.ToString() 是 正 確 的 。 即 使 一 個 常 數 ,C# 也 會 生 成 結 構 型 別 的 實 例 , 因<br />

此 也 可 以 使 用 結 構 型 別 的 方 法 , 例 如 :string s = 13.ToString() 是 正 確 的 。 簡 單 型 別 包 括 : 整 數 型<br />

別 、 字 元 型 別 、 布 爾 型 別 、 浮 點 數 型 別 、 十 進 制 型 別 。 見 下 表 :


保 留 字<br />

System 命 名 空<br />

間 中 的 名 字<br />

位 元<br />

組 數<br />

取 值 範 圍<br />

sbyte System.Sbyte 1 –128~127<br />

byte System.Byte 1 0~255<br />

short System.Int16 2 –32768~32767<br />

ushort System.UInt16 2 0~65535<br />

int System.Int32 4 –2147483648~2147483647<br />

uint System.UInt32 4 0~4292967295<br />

範 例<br />

long System.Int64 8 –9223372036854775808 long x = 36L;<br />

ulong System.UInt64 8 0~18446744073709551615 ulong x = 36UL;<br />

char System.Char 2 0~65535 char x = ' 中 ';<br />

float System.Single 4 3.4E-38~3.4E+38 float x = 23.56F;<br />

double System.Double 8 1.7E-308~1.7E+308 double x = 23.56D;<br />

bool System.Boolean 1 (true, false) bool x = true, y = false;<br />

decimal System.Decimal 16 正 負 1.0×10 −28 到 7.9×10 28 之 間 decimal x = 1.68M;<br />

C# 簡 單 型 別 使 用 方 法 和 C、C++ 中 相 應 的 資 料 型 別 基 本 一 致 。 需 要 注 意 的 是 :<br />

和 C 語 言 不 同 , 無 論 在 何 種 系 統 中 ,C# 每 種 資 料 型 別 所 佔 位 元 組 (byte) 數 是 固 定 的 。<br />

字 元 型 別 採 用 Unicode 字 元 集 , 一 個 Unicode 標 準 字 元 長 度 為 16 位 。<br />

整 數 型 別 不 能 被 隱 式 轉 換 為 字 元 型 別 (char), 例 如 char c1 = 10 是 錯 誤 的 , 必 須 寫 成 :char<br />

c1 = (char)10、char c = 'A'、char c = '\x0032'、char c = '\u0032'。<br />

布 爾 型 別 有 兩 個 值 :false,true。 不 能 認 為 整 數 0 是 false, 其 它 值 是 true。bool x = 1 是 錯<br />

誤 的 , 不 存 在 這 種 寫 法 , 只 能 寫 成 x = true 或 x = false。<br />

十 進 制 型 別 (decimal) 也 是 浮 點 數 型 別 , 只 是 精 度 比 較 高 , 一 般 用 於 財 政 金 融 計 算 。<br />

1.4.5 列 舉 型 別<br />

C# 列 舉 型 別 使 用 方 法 和 C、C++ 中 的 列 舉 型 別 基 本 一 致 。 見 下 例 :<br />

using System;<br />

class Class1<br />

{<br />

enum Days { Sat, Sun, Mon, Tue, Wed, Thu, Fri };<br />

添 加 邊 句<br />

// 使<br />

Visual Studio.Net,enum 語 用<br />

static void Main(string[] args)<br />

{<br />

Days day = Days.Tue;<br />

int x = (int)Days.Tue;//x=2<br />

[STAThread] 前 在<br />

Console.WriteLine("day={0}, x={1}", day, x);<br />

12


}<br />

}<br />

// :day=Tue, x=3 果 為 結 示 顯<br />

在 此 列 舉 型 別 Days 中 , 每 個 元 素 的 預 設 的 型 別 為 int, 其 中 Sat=0,Sun=1,Mon=2,<br />

Tue=3, 依 此 類 推 。 也 可 以 直 接 給 列 舉 元 素 指 派 值 。 例 如 :<br />

enum Days{Sat=1,Sun,Mon,Tue,Wed,Thu,Fri,Sat};<br />

在 此 列 舉 中 ,Sat=1,Sun=2,Mon=3,Tue=4,Wed=5, 等 等 。 和 C、C++ 中 不 同 ,C# 列 舉<br />

元 素 型 別 可 以 是 byte、sbyte 、short、ushort、int、uint、long 和 ulong 型 別 , 但 不 能 是 char<br />

型 別 。 見 下 例 :<br />

enum Days:byte{Sun,Mon,Tue,Wed,Thu,Fri,Sat};// 元<br />

型<br />

1.4.6 實 值 型 別 的 初 值 和 預 設 的 建 構 函 數<br />

所 有 變 數 都 要 求 必 須 有 初 值 , 如 沒 有 指 派 值 , 採 用 預 設 值 。 對 於 簡 單 型 別 ,sbyte、byte、<br />

short、ushort、int、uint、long 和 ulong 預 設 值 為 0,char 型 別 預 設 值 是 (char)0,float 為 0.0f,<br />

double 為 0.0d,decimal 為 0.0m,bool 為 false, 列 舉 型 別 為 0, 在 結 構 型 別 和 類 中 , 資 料<br />

成 員 的 實 值 型 別 變 數 設 置 為 預 設 值 , 參 照 型 別 變 數 設 置 為 null。<br />

可 以 顯 式 的 指 派 值 , 例 如 int i = 0。 而 對 於 複 雜 結 構 型 別 , 其 中 的 每 個 資 料 成 員 都 按 此 種<br />

方 法 指 派 值 , 顯 得 過 於 麻 煩 。 由 於 實 值 型 別 都 是 結 構 型 別 , 可 用 new 語 句 調 用 其 建 構 函 數 初<br />

始 化 實 值 型 別 變 數 , 例 如 :int j = new int()。 請 注 意 , 用 new 語 句 並 不 是 把 int 變 數 變 為 參 照<br />

變 數 ,j 仍 是 實 值 型 別 變 數 , 這 裡 new 僅 僅 是 調 用 其 建 構 函 數 。 所 有 的 實 值 型 別 都 有 預 設 的<br />

的 無 參 數 的 建 構 函 數 , 其 功 能 就 是 為 該 實 值 型 別 賦 初 值 為 預 設 值 。 對 於 自 定 義 結 構 型 別 , 由 於<br />

已 有 預 設 的 的 無 參 數 的 建 構 函 數 , 不 能 再 定 義 無 參 數 的 建 構 函 數 , 但 可 以 定 義 有 參 數 的 建 構 函<br />

數 。<br />

byte 為 素<br />

別<br />

1.4.7 參 照 型 別 分 類<br />

C# 語 言 中 參 照 型 別 可 以 分 為 以 下 幾 種 :<br />

類 :C# 語 言 中 預 定 義 了 一 些 類 : 對 象 類 (object 類 )、 陣 列 類 、 字 串 類 等 。 當 然 , 程 式 設 計<br />

師 可 以 定 義 其 它 類 。<br />

介 面 。<br />

委 派 。<br />

C# 語 言 參 照 型 別 變 數 無 論 如 何 定 義 , 總 是 參 照 型 別 變 數 , 不 會 變 為 實 值 型 別 變 數 。C# 語<br />

言 參 照 型 別 對 象 一 般 用 運 算 子 new 建 立 , 用 參 照 型 別 變 數 引 用 該 對 象 。 本 節 僅 介 紹 對 象 型 別<br />

(object 型 別 )、 字 串 型 別 、 陣 列 。 其 它 型 別 在 其 它 節 中 介 紹 。<br />

13


用<br />

,arr[i]<br />

1.4.8 對 象 類 (object class)<br />

C# 中 的 所 有 型 別 ( 包 括 數 值 型 別 ) 都 直 接 或 間 接 地 以 object 類 為 基 類 。 對 象 類 (object 類 ) 是 所<br />

有 其 它 類 的 基 類 。 任 何 一 個 類 定 義 , 如 果 不 指 定 基 類 , 預 設 object 為 基 類 。 繼 承 和 基 類 的 概 念<br />

見 以 後 章 節 。C# 語 言 規 定 , 基 類 的 參 照 變 數 可 以 引 用 衍 生 類 的 對 象 ( 注 意 , 衍 生 類 的 參 照 變 數<br />

不 可 以 引 用 基 類 的 對 象 ), 因 此 , 對 一 個 object 的 變 數 可 以 賦 予 任 何 型 別 的 值 :<br />

int x = 25;<br />

object obj1;<br />

obj1 = x;<br />

object obj2 = 'A';<br />

object 關 鍵 字 是 在 命 名 空 間 System 中 定 義 的 , 是 類 System.Object 的 別 名 。<br />

1.4.9 陣 列 類<br />

在 進 行 批 次 處 理 資 料 的 時 候 , 要 用 到 陣 列 。 陣 列 是 一 組 型 別 相 同 的 有 序 資 料 。 陣 列 按 照 陣<br />

列 名 、 資 料 元 素 的 型 別 和 維 數 來 進 行 描 述 。C# 語 言 中 陣 列 是 類 System.Array 類 對 象 , 比 如 宣 告<br />

一 個 整 數 型 陣 列 :int[] arr = new int[5];, 實 際 上 產 生 了 一 個 陣 列 類 對 象 ,arr 是 這 個 對 象 的 參 照<br />

( 地 址 )。<br />

在 C# 中 陣 列 可 以 是 一 維 的 , 也 可 以 是 多 維 的 , 同 樣 也 支 援 陣 列 的 陣 列 , 即 陣 列 的 元 素 還<br />

是 陣 列 。 一 維 陣 列 最 為 普 遍 , 用 的 也 最 多 。 我 們 先 看 一 個 一 維 陣 列 的 例 子 :<br />

using System;<br />

class Test<br />

{<br />

static void Main()<br />

{<br />

}<br />

}<br />

int[] arr = new int[3];// new 算 子 建 立 一 個 個 元 素 的 一 維 陣 列 類 變 數 , 運<br />

for (int i = 0; i < arr.Length; i++)/* arr.Length<br />

*/ 示 陣 列 元 素 個 數 表 是<br />

arr[i] = i * i;// i 元 素 指 派 初 值 表 示 第 個 元 素 的 值 列 第 一 個 元 素 的 下 標 為 列 陣<br />

for (int i = 0; i < arr.Length; i++)// 陣<br />

Console.WriteLine("arr[{0}] = {1}", i, arr[i]);<br />

這 段 程 式 碼 產 生 了 一 個 int 型 別 3 個 元 素 的 一 維 陣 列 , 初 始 化 後 逐 項 輸 出 。 其 中 arr.Length<br />

表 示 陣 列 元 素 的 個 數 。 注 意 陣 列 定 義 不 能 寫 為 C 語 言 格 式 :int arr[]。 程 序 的 輸 出 為 :<br />

arr[0] = 0<br />

arr[1] = 1<br />

14


計<br />

算<br />

科<br />

機<br />

科<br />

學<br />

,a4[1,1]=5<br />

arr[2] = 4<br />

上 面 的 例 子 中 使 用 的 是 一 維 陣 列 , 下 面 介 紹 多 維 陣 列 :<br />

string a1 類 參 照 變 數 列 維<br />

string[] a1;// 一<br />

string[,] a2;// 二<br />

string 維 陣<br />

a2 = new string[2,3];<br />

a2[1,2] = "abc";<br />

列 類 參 照 變 陣<br />

a2<br />

string[,,] a3;// string a3<br />

列 類 參 照 變 數 列 的 陣 列 , 即 陣 列 的 元 素 還 是 陣 列 陣 維 三<br />

string[][] j2;// 陣<br />

string[][][][] j3;<br />

在 陣 列 宣 告 的 時 候 , 可 以 對 陣 列 元 素 進 行 指 派 值 。 看 下 面 的 例 子 :<br />

3 列 , 有 元 素 。 陣 維<br />

int[] a1 = new int[]{1,2,3};// 一<br />

int[] a2 = new int[3]{1,2,3};// 此<br />

int[] a3 = {1,2,3};// 相<br />

格 式 也 正 確 個<br />

a3=new int[]{1,2,3};<br />

int[,] a4 = new int[,]{{1,2,3},{4,5,6}};// 二<br />

int[][] j2 = new int[3][];// 有 義 第 一 個 元 素 , 是 一 個 陣 列 定<br />

j2[0] = new int[]{1,2,3};// 定<br />

j2[1] = new int[]{1, 2, 3, 4, 5, 6};// 個 元 素 的 陣 列 可 以 不 等 長 每<br />

j2[2] = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};<br />

維 陣 列<br />

1.4.10 字 串 類 (string 類 )<br />

int[] 於 當<br />

陣 列 j2, 義<br />

個 元 素 , 每 個 元 素 都 是 一 個 陣 列 三<br />

C# 還 定 義 了 一 個 基 本 的 類 string, 專 門 用 於 對 字 串 的 操 作 。 這 個 類 也 是 在 命 名 空 間 System<br />

中 定 義 的 , 是 類 System.String 的 別 名 。 字 串 應 用 非 常 廣 泛 , 在 string 類 的 定 義 中 封 裝 了 許 多<br />

方 法 , 下 面 的 一 些 語 句 展 示 了 string 類 的 一 些 典 型 用 法 :<br />

字 串 定 義<br />

string s;// s<br />

s<br />

個 字 串 參 照 型 別 變 數 串 參 照 型 別 變 數 向 字 一 義 定<br />

s = "Zhang";// 字<br />

string FirstName = "Ming";<br />

string LastName = "Zhang";<br />

指<br />

"Zhang" 串<br />

string Name = FirstName+" "+LastName;// 算 運<br />

string SameName = Name;<br />

',' ',' ','<br />

char[] s2 = {'<br />

string s3 = new String(s2);<br />

字 串 搜 索<br />

string s = "ABC 科<br />

int i = s.IndexOf("<br />

',' '};<br />

搜 索 " 科 " 在 字 串 中 的 位 置 , 因 第 一 個 字 元 索 引 為 0, 所 以 "A" 索 引 為 0," 科 " 索 引 為 3, 因<br />

+ 已 子<br />

多 載 被<br />

此 這 裡 i = 3, 如 沒 有 此 字 串 i = –1。 注 意 C# 中 ,ASCII 和 漢 字 都 用 2 個 位 元 組 表 示 。<br />

15<br />

學 ";<br />

");


空<br />

取<br />

字 串 比 較 函 數<br />

string s1 = "abc";<br />

string s2 = "abc";<br />

int n = string.Compare(s1,s2);//n = 0<br />

n 值 得 到 0 表 示 兩 個 字 串 相 同 ,n 值 小 於 零 , 表 示 s1 < s2,n 值 大 於 零 , 表 示 s1 > s2。 此<br />

方 法 區 分 大 小 寫 。 也 可 用 如 下 辦 法 比 較 字 串 :<br />

string s1 = "abc";<br />

string s = "abc";<br />

"; 同 相<br />

string s2 = "<br />

可 用 !=。<br />

不<br />

if(s == s1)// 還<br />

s2 = " 相<br />

"; 同<br />

判 斷 是 否 為 空 字 串<br />

string s = "";<br />

string s1 = " 不<br />

if(s.Length == 0)<br />

";<br />

s1 = "<br />

得 到 子 字 串 或 字 元<br />

字 子<br />

string s = " 取<br />

雖<br />

"; 空<br />

"; 串<br />

string sb = s.Substring(2,2);//<br />

'<br />

引 索 從<br />

char sb1 = s[0];//sb1='<br />

Console.WriteLine(sb1);// 示 : 取 顯<br />

字 串 刪 除 函 數<br />

string s = " "; 字 串 子 取<br />

string sb = s.Remove(0,2);// 索 引 從<br />

插 入 字 串<br />

string s = " "; 機 科 學 算 計<br />

string s1 = s.Insert(3, " 軟<br />

字 串 替 換 函 數<br />

string s = " "; 機 科 學 算 計<br />

string s1 = s.Replace(" 算 計<br />

把 string 轉 換 為 字 元 陣 列<br />

機 科 算<br />

string s = " 計<br />

"; 學<br />

String 是 參 照 型 別 , 但 此 寫 法 仍 可 比 較 兩 個 字 串 的 值 然<br />

0 開 為<br />

2 開 為<br />

2 個 字 元 取 始<br />

2 個 除<br />

,Sb=" 字<br />

,Sb=" 字<br />

");//s1=" ",s 元 始 刪 字<br />

機 軟 件 科 學 內 容 不 變 算 計 件<br />

"," 軟 機<br />

");//s1=" 軟 件<br />

char[] s2 = s.ToCharArray(0, S.Length);// 屬<br />

其 它 資 料 型 別 轉 換 為 字 串<br />

int i = 9;<br />

string s8 = i.ToString();//s8="9"<br />

float n = 1.9f;<br />

string s9 = n.ToString();//s8="1.9"<br />

科 件<br />

為<br />

",s 內 學<br />

",s 內 串<br />

不 變 容<br />

",s 內 容 不 變 串<br />

不 變 容<br />

16<br />

性 Length<br />

串 類 對 象 的 長 度 字


,s<br />

其 它 資 料 型 別 都 可 用 此 方 法 轉 換 為 字 串 類 對 象<br />

大 小 寫 轉 換<br />

string s = "AaBbCc";<br />

string s1 = s.ToLower();// 小 內 字 元 轉 換 為 大 寫 容 不 變 把<br />

string s2 = s.ToUpper();// 把<br />

刪 除 所 有 的 空 格<br />

string s = "A bc ";<br />

所 有 的 空 除<br />

s.Trim();// 刪<br />

string 類 其 它 方 法 的 使 用 請 用 幫 助 系 統 查 看 , 方 法 是 打 開 Visual Studio.Net 的 程 式 碼 編 輯<br />

格<br />

,s 內<br />

器 , 鍵 入 string, 將 游 標 移 到 鍵 入 的 字 串 string 上 , 然 後 按 F1 鍵 。<br />

1.4.11 型 別 轉 換<br />

在 編 寫 C# 語 言 程 式 時 , 經 常 會 碰 到 型 別 轉 換 問 題 。 例 如 整 數 和 浮 點 數 相 加 ,C# 會 進 行 隱<br />

式 轉 換 。 詳 細 記 住 那 些 型 別 資 料 可 以 轉 換 為 其 它 型 別 資 料 , 是 不 可 能 的 , 也 是 不 必 要 的 。 程 式<br />

設 計 師 應 記 住 型 別 轉 換 的 一 些 基 本 原 則 , 編 譯 器 在 轉 換 發 生 問 題 時 , 會 給 提 示 。C# 語 言 中 型<br />

別 轉 換 分 為 : 隱 式 轉 換 、 顯 示 轉 換 、 裝 箱 (boxing) 和 拆 箱 (unboxing) 等 三 種 。<br />

一 、 隱 式 轉 換<br />

隱 式 轉 換 就 是 系 統 預 設 的 的 、 不 需 要 加 以 宣 告 就 可 以 進 行 的 轉 換 。 例 如 從 int 型 別 轉 換 到<br />

long 型 別 就 是 一 種 隱 式 轉 換 。 在 隱 式 轉 換 過 程 中 , 轉 換 一 般 不 會 失 敗 , 轉 換 過 程 中 也 不 會 導 致<br />

訊 息 丟 失 。 例 如 :<br />

int i = 10;<br />

long l = i;<br />

二 、 顯 示 轉 換<br />

顯 式 型 別 轉 換 , 又 叫 強 制 型 別 轉 換 。 與 隱 式 轉 換 正 好 相 反 , 顯 式 轉 換 需 要 明 確 地 指 定 轉 換<br />

型 別 , 顯 示 轉 換 可 能 導 致 訊 息 丟 失 。 下 面 的 例 子 把 長 整 數 型 變 數 顯 式 轉 換 為 整 數 型 :<br />

long l = 5000;<br />

int i = (int)l;// 果 超 如<br />

三 、 裝 箱 (boxing) 和 拆 箱 (unboxing)<br />

int 取 過<br />

裝 箱 (boxing) 和 拆 箱 (unboxing) 是 C# 語 言 型 別 系 統 提 出 的 核 心 概 念 , 裝 箱 是 實 值 型 別 轉 換 為<br />

object( 對 象 ) 型 別 , 拆 箱 是 object( 對 象 ) 型 別 轉 換 為 實 值 型 別 。 有 了 裝 箱 和 拆 箱 的 概 念 , 對 任 何<br />

型 別 的 變 數 來 說 , 最 終 我 們 都 可 以 看 作 是 object 型 別 。<br />

1. 裝 箱 操 作<br />

把 一 個 實 值 型 別 變 數 裝 箱 也 就 是 產 生 一 個 object 對 象 , 並 將 這 個 實 值 型 別 變 數 的 值 複 製 給<br />

這 個 object 對 象 。 例 如 :<br />

int i = 10;<br />

object obj = i;// 隱<br />

範 圍 , 將 產 生 異 常 值<br />

,obj 為<br />

對<br />

我 們 也 可 以 用 顯 式 的 方 法 來 進 行 裝 箱 操 作 , 例 如 :<br />

17<br />

式 裝 箱 操 作<br />

object 的 生 產<br />

的 參 照 。 象


int i =10;<br />

object obj = object(i);// 式 裝 箱 操 顯<br />

實 值 型 別 的 值 裝 箱 後 , 實 值 型 別 變 數 的 值 不 變 , 僅 將 這 個 實 值 型 別 變 數 的 值 複 製 給 這 個<br />

作<br />

object 對 象 。 我 們 看 一 下 下 面 的 程 式 :<br />

using System<br />

class Test<br />

{<br />

}<br />

public static void Main()<br />

{<br />

}<br />

int n = 200;<br />

object o = n;<br />

改 能<br />

o = 201;// 不<br />

n 變<br />

Console.WriteLine("{0}, {1}", n, o);<br />

輸 出 結 果 為 :200, 201。 這 就 證 明 了 實 值 型 別 變 數 n 和 object 類 對 象 o 都 獨 立 存 在 著 。<br />

2. 拆 箱 操 作<br />

和 裝 箱 操 作 正 好 相 反 , 拆 箱 操 作 是 指 將 一 個 對 象 型 別 顯 式 地 轉 換 成 一 個 實 值 型 別 。 拆 箱 的<br />

過 程 分 為 兩 步 : 首 先 檢 查 這 個 object 對 象 , 看 它 是 否 為 給 定 的 實 值 型 別 的 裝 箱 值 , 然 後 , 把 這<br />

個 對 象 的 值 複 製 給 實 值 型 別 的 變 數 。 我 們 舉 個 例 子 來 看 看 一 個 對 象 拆 箱 的 過 程 :<br />

int i = 10;<br />

object obj = i;<br />

int j = (int)obj;// 箱 操 拆<br />

可 以 看 出 拆 箱 過 程 正 好 是 裝 箱 過 程 的 逆 過 程 , 必 須 注 意 裝 箱 操 作 和 拆 箱 操 作 必 須 遵 循 型 別<br />

作<br />

兼 容 的 原 則 。<br />

3. 裝 箱 和 拆 箱 的 使 用<br />

定 義 如 下 函 數 :<br />

void Display(Object o)// ,o Object 為 型 意 注<br />

{<br />

}<br />

int x=(int)o;// 拆<br />

System.Console.WriteLine("{0},{1}",x,o);<br />

箱 別<br />

調 用 此 函 數 :int y = 20; Display(y); 在 此 利 用 了 裝 箱 概 念 , 形 參 被 實 參 替 換 :Object o = y,<br />

也 就 是 說 , 函 數 的 參 數 是 Object 型 別 , 可 以 將 任 意 型 別 實 參 傳 遞 給 函 數 。<br />

18<br />

1.5 運 算 子<br />

C# 語 言 和 C 語 言 的 運 算 子 用 法 基 本 一 致 。 以 下 重 點 講 解 二 者 之 間 不 一 致 部 分 。


1.5.1 運 算 子 分 類<br />

與 C 語 言 一 樣 , 如 果 按 照 運 算 子 所 作 用 的 運 算 元 個 數 來 分 ,C# 語 言 的 運 算 子 可 以 分 為 以 下<br />

幾 種 類 型 :<br />

一 元 運 算 子 : 一 元 運 算 子 作 用 於 一 個 運 算 元 , 例 如 :–x、++x、x-- 等 。<br />

二 元 運 算 子 : 二 元 運 算 子 對 兩 個 運 算 元 進 行 運 算 , 例 如 :x+y。<br />

三 元 運 算 子 : 三 元 運 算 子 只 有 一 個 :x y:z。<br />

C# 語 言 運 算 子 的 詳 細 分 類 及 運 算 子 從 高 到 低 的 優 先 級 順 序 見 下 表 。<br />

分 類 運 算 子 結 合 性<br />

初 級 (x) x.y f(x) a[x] x++ x–– new typeof sizeof checked unchecked 左<br />

單 元 + – ! ~ ++x ––x (T)x 左<br />

乘 法 等 * / % 左<br />

加 法 等 + – 左<br />

移 位 > 左<br />

關 係 < > = is as 左<br />

相 等 == != 右<br />

邏 輯 與 & 左<br />

邏 輯 異 或 ^<br />

左<br />

邏 輯 或 | 左<br />

條 件 與 && 左<br />

條 件 或 || 左<br />

條 件 : 右<br />

指 派 等 = *= /= %= += –= = &= ^= |= 右<br />

1.5.2 測 試 運 算 子 is<br />

is 運 算 子 用 於 動 態 地 檢 查 表 達 式 是 否 為 指 定 型 別 。 使 用 格 式 為 :e is T, 其 中 e 是 一 個 表 達<br />

式 ,T 是 一 個 型 別 , 該 式 判 斷 e 是 否 為 T 型 別 , 返 回 值 是 一 個 布 爾 值 。 例 子 :<br />

using System;<br />

class Test<br />

{<br />

public static void Main()<br />

{<br />

Console.WriteLine(1 is int);<br />

Console.WriteLine(1 is float);<br />

Console.WriteLine(1.0f is float);<br />

19


Console.WriteLine(1.0d is double);<br />

}<br />

}<br />

輸 出 為 :<br />

True<br />

False<br />

True<br />

True<br />

1.5.3 typeof 運 算 子<br />

typeof 運 算 子 用 於 獲 得 指 定 型 別 在 System 命 名 空 間 中 定 義 的 型 別 名 字 , 例 如 :<br />

using System;<br />

class Test<br />

{<br />

static void Main()<br />

{<br />

Console.WriteLine(typeof(int));<br />

Console.WriteLine(typeof(System.Int32));<br />

Console.WriteLine(typeof(string));<br />

Console.WriteLine(typeof(double[]));<br />

}<br />

}<br />

產 生 如 下 輸 出 , 由 輸 出 可 知 int 和 System.int32 是 同 一 型 別 。<br />

System.Int32<br />

System.Int32<br />

System.String<br />

System.Double[]<br />

1.5.4 溢 出 檢 查 運 算 子 checked 和 unchecked<br />

在 進 行 整 數 型 算 術 運 算 ( 如 +、-、*、/ 等 ) 或 從 一 種 整 數 型 顯 式 轉 換 到 另 一 種 整 數 型 時 , 有<br />

可 能 出 現 運 算 結 果 超 出 這 個 結 果 所 屬 型 別 值 域 的 情 況 , 這 種 情 況 稱 之 為 溢 出 。 整 數 型 算 術 運 算<br />

表 達 式 可 以 用 checked 或 unchecked 溢 出 檢 查 運 算 子 , 決 定 在 編 譯 和 執 行 時 是 否 對 表 達 式 溢 出<br />

進 行 檢 查 。 如 果 表 達 式 不 使 用 溢 出 檢 查 運 算 子 或 使 用 了 checked 運 算 子 , 常 數 表 達 式 溢 出 , 在<br />

編 譯 時 將 產 生 錯 誤 , 表 達 式 中 包 含 變 數 , 程 序 執 行 時 執 行 該 表 達 式 產 生 溢 出 , 將 產 生 異 常 提 示<br />

訊 息 。 而 使 用 了 unchecked 運 算 子 的 表 達 式 語 句 , 即 使 表 達 式 產 生 溢 出 , 編 譯 和 執 行 時 都 不 會<br />

產 生 錯 誤 提 示 。 但 這 往 往 會 出 現 一 些 不 可 預 期 的 結 果 , 所 以 使 用 unchecked 運 算 子 要 小 心 。<br />

20


用<br />

用<br />

,arr<br />

下 面 的 例 子 說 明 了 checked 和 unchecked 運 算 子 的 用 法 :<br />

using System;<br />

class Class1<br />

{<br />

}<br />

static void Main(string[] args)<br />

{<br />

}<br />

const int x = int.MaxValue;<br />

查 溢 出 檢<br />

unchecked// 不<br />

{<br />

}<br />

int z = x*2;// ,z = –2 產 生 編 譯 錯 誤 不 時 譯 編<br />

Console.WriteLine("z={0}", z);// 顯<br />

checked// 查 溢 出 檢<br />

1.5.5 new 運 算 子<br />

{<br />

}<br />

int z1 = (x*2);// 譯 時 會 產 生 編 譯 錯 誤 編<br />

Console.WriteLine("z = {0}", z1);<br />

–2 示<br />

new 運 算 子 可 以 產 生 實 值 型 別 變 數 、 參 照 型 別 對 象 , 同 時 自 動 調 用 建 構 函 數 。 例 如 :<br />

int x = new int();//<br />

產<br />

Person C1 = new Person ();//<br />

int[] arr=new int[2];// 陣<br />

建<br />

// Person 型<br />

類<br />

是<br />

是<br />

需 注 意 的 是 ,int x = new int() 語 句 將 自 動 調 用 int 結 構 不 帶 參 數 的 建 構 函 數 , 給 x 賦 初 值 0,<br />

照<br />

x 仍 是 實 值 型 別 變 數 , 不 會 變 為 參 照 型 別 變 數 。<br />

列 也 是 類 , 產 生 陣 列 類 對 象<br />

陣 列 對 象 的 參<br />

new<br />

整 數 型 變 數 x, 調 用 預 設 的 建 構 函 數 生<br />

new<br />

Person 的 立<br />

象 。 對<br />

1.5.6 運 算 子 的 優 先 級<br />

C1 數 變 別<br />

象 的 參 照 對<br />

當 一 個 表 達 式 包 含 多 種 運 算 子 時 , 運 算 子 的 優 先 級 控 制 著 運 算 子 求 值 的 順 序 。 例 如 , 表 達<br />

式 x+y*z 按 照 x+(y*z) 順 序 求 值 , 因 為 * 運 算 子 比 + 運 算 子 有 更 高 的 優 先 級 。 這 和 數 學 運 算 中 的 先<br />

乘 除 後 加 減 是 一 致 的 。1.5.1 節 中 的 表 總 結 了 所 有 運 算 子 從 高 到 低 的 優 先 級 順 序 。<br />

當 兩 個 有 相 同 優 先 級 的 運 算 子 對 運 算 元 進 行 運 算 時 , 例 如 x+y–z, 運 算 子 按 照 出 現 的 順 序<br />

由 左 至 右 執 行 ,x+y–z 按 (x+y)–z 進 行 求 值 。 指 派 運 算 子 按 照 右 接 合 的 原 則 , 即 操 作 按 照 從 右 向<br />

左 的 順 序 執 行 。 如 x=y=z 按 照 x=(y=z) 進 行 求 值 。 建 議 在 寫 表 達 式 的 時 候 , 如 果 無 法 確 定 運 算 子<br />

21


的 實 際 順 序 , 則 盡 量 採 用 括 號 來 保 證 運 算 的 順 序 , 這 樣 也 使 得 程 式 一 目 瞭 然 , 而 且 自 己 在 編 程<br />

時 能 夠 思 路 清 晰 。<br />

1.6 程 序 控 制 語 句<br />

C# 語 言 控 制 語 句 和 C 基 本 相 同 , 使 用 方 法 基 本 一 致 。C# 語 言 控 制 語 句 包 括 :if 語 句 、swith<br />

語 句 、while 語 句 、do…while 語 句 、for 語 句 、foreach 語 句 、break 語 句 、continue 語 句 、goto<br />

語 句 、return 語 句 、 異 常 處 理 語 句 等 , 其 中 foreach 語 句 和 異 常 語 句 是 C# 語 言 新 增 加 控 制 語<br />

句 。<br />

本 節 首 先 介 紹 一 下 這 些 語 句 和 C 語 言 的 不 同 點 , 然 後 介 紹 C# 語 言 新 增 的 控 制 語 句 。<br />

1.6.1 和 C 語 言 的 不 同 點<br />

<br />

與 C 不 同 ,if 語 句 、while 語 句 、do…while 語 句 、for 語 句 中 的 判 斷 語 句 , 一 定 要 用 布 爾<br />

表 達 式 , 不 能 認 為 0 為 false, 其 它 數 為 true。<br />

switch 語 句 不 再 支 援 遍 歷 ,C 和 C++ 語 言 允 許 switch 語 句 中 case 標 籤 後 不 出 現 break 語 句 ,<br />

但 C# 不 允 許 這 樣 , 它 要 求 每 個 case 標 籤 項 後 使 用 break 語 句 或 goto 跳 轉 語 句 , 即 不 允 許<br />

從 一 個 case 自 動 遍 歷 到 其 它 case, 否 則 編 譯 時 將 報 錯 。switch 語 句 的 控 制 型 別 , 即 其 中 控<br />

制 表 達 式 的 資 料 型 別 可 以 是 sbyte、byte、short、ushort、uint、long、ulong、char、string<br />

或 列 舉 型 別 。 每 個 case 標 籤 中 的 常 數 表 達 式 必 須 屬 於 或 能 隱 式 轉 換 成 控 制 型 別 。 如 果 有<br />

兩 個 或 兩 個 以 上 case 標 籤 中 的 常 數 表 達 式 值 相 同 , 編 譯 時 將 會 報 錯 。 執 行 switch 語 句 ,<br />

首 先 計 算 switch 表 達 式 , 然 後 與 case 後 的 常 數 表 達 式 的 值 進 行 比 較 , 執 行 第 一 個 與 之 匹<br />

配 的 case 分 支 下 的 語 句 。 如 果 沒 有 case 常 數 表 達 式 的 值 與 之 匹 配 , 則 執 行 default 分 支 下<br />

的 語 句 , 如 果 沒 有 default 語 句 , 則 退 出 switch 語 句 。switch 語 句 中 可 以 沒 有 default 語 句 ,<br />

但 最 多 只 能 有 一 個 default 語 句 。 見 下 例 :<br />

using System;<br />

class class1<br />

{<br />

static void Main()<br />

{<br />

System.Console.WriteLine(" "); 入 要 計 算 天 數 的 月 份 輸 請<br />

string s = System.Console.ReadLine();<br />

string s1 = "";<br />

switch(s)<br />

{<br />

case "1": case "3": case "5":<br />

case "7": case "8": case "10":<br />

一 條 語 句 用<br />

case "12":// 共<br />

22


}<br />

}<br />

}<br />

s1 = "31"; break;<br />

case "2":<br />

s1 = "28"; break;<br />

case "4": case "6": case "9":<br />

僅 為 說 明 問 題 , 無 此 必 要 句<br />

goto case "11";//goto 語<br />

case "11":<br />

s1 = "30"; break;<br />

default:<br />

s1 = " "; break; 誤 錯 入 輸<br />

System.Console.WriteLine(s1);<br />

1.6.2 foreach 語 句<br />

foreach 語 句 是 C# 語 言 新 引 入 的 語 句 ,C 和 C++ 中 沒 有 這 個 語 句 , 它 借 用 Visual Basic 中 的<br />

foreach 語 句 。 語 句 的 格 式 為 :<br />

foreach( 型 別 變 數 名 in 表 達 式 ) 循 環 語 句<br />

其 中 表 達 式 必 須 是 一 個 陣 列 或 其 它 集 合 型 別 , 每 一 次 循 環 從 陣 列 或 其 它 集 合 中 逐 一 取 出 資 料 ,<br />

指 派 給 指 定 型 別 的 變 數 , 該 變 數 可 以 在 循 環 語 句 中 使 用 、 處 理 , 但 不 允 許 修 改 變 數 , 該 變 數 的<br />

指 定 型 別 必 須 和 表 達 式 所 代 表 的 陣 列 或 其 它 集 合 中 的 資 料 型 別 一 致 。 例 子 :<br />

using System;<br />

class Test()<br />

{<br />

public static void Main()<br />

{<br />

}<br />

}<br />

int[] list = {10, 20, 30, 40};// 陣<br />

foreach(int m in list)<br />

Console.WriteLine("{0}", m);<br />

對 於 一 維 陣 列 ,foreach 語 句 循 環 順 序 是 從 下 標 為 0 的 元 素 開 始 一 直 到 陣 列 的 最 後 一 個 元<br />

列<br />

素 。 對 於 多 維 陣 列 , 元 素 下 標 的 遞 增 是 從 最 右 邊 那 一 維 開 始 的 。 同 樣 break 和 continue 可 以 出<br />

現 在 foreach 語 句 中 , 功 能 不 變 。<br />

23


1.6.3 異 常 語 句<br />

在 編 寫 程 序 時 , 不 僅 要 關 心 程 序 的 正 常 操 作 , 還 應 該 考 慮 到 程 序 執 行 時 可 能 發 生 的 各 類 不<br />

可 預 期 的 事 件 , 比 如 用 戶 輸 入 錯 誤 、 記 憶 體 不 夠 、 磁 碟 出 錯 、 網 路 資 源 不 可 用 、 資 料 庫 無 法 使<br />

用 等 , 所 有 這 些 錯 誤 被 稱 作 異 常 或 例 外 (exception), 不 能 因 為 這 些 異 常 使 程 序 執 行 產 生 問 題 。<br />

各 種 程 序 設 計 語 言 經 常 採 用 異 常 處 理 語 句 來 解 決 這 類 異 常 問 題 。<br />

C# 提 供 了 一 種 處 理 系 統 級 錯 誤 和 應 用 程 序 級 錯 誤 的 結 構 化 的 、 統 一 的 、 型 別 安 全 的 方 法 。<br />

C# 異 常 語 句 包 含 try 子 句 、catch 子 句 和 finally 子 句 。try 子 句 中 包 含 可 能 產 生 異 常 的 語 句 , 該<br />

子 句 自 動 捕 捉 執 行 這 些 語 句 過 程 中 發 生 的 異 常 。catch 子 句 中 包 含 了 對 不 同 異 常 的 處 理 程 式<br />

碼 , 可 以 包 含 多 個 catch 子 句 , 每 個 catch 子 句 中 包 含 了 一 個 異 常 型 別 , 這 個 異 常 型 別 必 須 是<br />

System.Exception 類 或 它 的 衍 生 類 參 照 變 數 , 該 語 句 只 捕 捉 該 型 別 的 異 常 。 可 以 有 一 個 通 用 異<br />

常 型 別 的 catch 子 句 , 該 catch 子 句 一 般 在 事 先 不 能 確 定 會 發 生 什 麼 樣 的 異 常 的 情 況 下 使 用 ,<br />

也 就 是 可 以 捕 捉 任 意 型 別 的 異 常 。 一 個 異 常 語 句 中 只 能 有 一 個 通 用 異 常 型 別 的 catch 子 句 , 而<br />

且 如 果 有 的 話 , 該 catch 子 句 必 須 排 在 其 它 catch 子 句 的 後 面 。 無 論 是 否 產 生 異 常 , 子 句 finally<br />

一 定 被 執 行 , 在 finally 子 句 中 可 以 增 加 一 些 必 須 執 行 的 語 句 。<br />

異 常 語 句 捕 捉 和 處 理 異 常 的 機 理 是 : 當 try 子 句 中 的 程 式 碼 產 生 異 常 時 , 按 照 catch 子 句<br />

的 順 序 查 找 異 常 型 別 。 如 果 找 到 , 執 行 該 catch 子 句 中 的 異 常 處 理 語 句 。 如 果 沒 有 找 到 , 執 行<br />

通 用 異 常 型 別 的 catch 子 句 中 的 異 常 處 理 語 句 。 由 於 異 常 的 處 理 是 按 照 catch 子 句 出 現 的 順 序<br />

逐 一 檢 查 catch 子 句 , 因 此 catch 子 句 出 現 的 順 序 是 很 重 要 的 。 無 論 是 否 產 生 異 常 , 一 定 執 行<br />

finally 子 句 中 的 語 句 。 異 常 語 句 中 不 必 一 定 包 含 所 有 三 個 子 句 , 因 此 異 常 語 句 可 以 有 以 下 三 種<br />

可 能 的 形 式 :<br />

try-catch 語 句 , 可 以 有 多 個 catch 語 句<br />

try-finally 語 句<br />

try-catch-finally 語 句 , 可 以 有 多 個 catch 語 句<br />

請 看 下 邊 的 例 子 :<br />

1. try-catch-finally 語 句<br />

using System<br />

using System.IO//<br />

public class Example<br />

{<br />

public static void Main()<br />

命 名 空 間 的 用 引 須 必 件 文 用 使<br />

{<br />

StreamReader sr = null;// 必<br />

try<br />

{<br />

否<br />

sr = File.OpenText("d:\\csarp\\test.txt");// 能 產 生 異 常 可<br />

string s;<br />

24<br />

null, 予 初 值 賦 須<br />

編 譯 不 能 通 過 則


}<br />

}<br />

}<br />

while(sr.Peek() != –1)<br />

{<br />

}<br />

s = sr.ReadLine();// 能 產 生 異 常 可<br />

Console.WriteLine(s);<br />

catch(DirectoryNotFoundException e)// 指 定 目 錄 異 常 無<br />

{<br />

}<br />

Console.WriteLine(e.Message);<br />

catch(FileNotFoundException e)// 指 定 文 件 異 常 無<br />

{<br />

}<br />

Console.WriteLine(" 文<br />

catch(Exception e)// 其<br />

{<br />

}<br />

finally<br />

{<br />

}<br />

2. try-finally 語 句<br />

Console.WriteLine(" 處<br />

if(sr != null) sr.Close();<br />

"+e.FileName+" 未 件<br />

"); 現<br />

發 所 有 異 常 被<br />

:{0}",e.Message); 失 敗 它 理<br />

上 例 中 , 其 實 可 以 不 用 catch 語 句 , 在 finally 子 句 中 把 文 件 關 閉 , 提 示 用 戶 是 否 正 確 打 開<br />

了 文 件 , 請 讀 者 自 己 完 成 。<br />

3. try-catch 語 句<br />

請 讀 者 把 上 例 修 改 為 使 用 try-catch 結 構 , 注 意 在 每 個 catch 語 句 中 都 要 關 閉 文 件 。<br />

1.7 類 的 繼 承<br />

在 1.3 節 , 定 義 了 一 個 描 述 個 人 情 況 的 類 Person, 如 果 我 們 需 要 定 義 一 個 僱 員 類 , 當 然 可<br />

以 從 頭 開 始 定 義 僱 員 類 Employee。 但 這 樣 不 能 利 用 Person 類 中 已 定 義 的 函 數 和 資 料 。 比 較 好<br />

的 方 法 是 , 以 Person 類 為 基 礎 ( 基 類 ), 衍 生 出 一 個 僱 員 類 Employee, 僱 員 類 Employee 繼 承 了<br />

Person 類 的 資 料 成 員 和 函 數 成 員 , 既 Person 類 的 資 料 成 員 和 函 數 成 員 成 為 Employee 類 的 成<br />

員 。 這 個 Employee 類 稱 為 以 Person 類 為 基 類 的 衍 生 類 , 這 是 C# 給 我 們 提 出 的 方 法 。C# 用 繼 承<br />

的 方 法 , 實 現 程 式 碼 的 重 用 。<br />

25


:{0}<br />

1.7.1 衍 生 類 的 宣 告 格 式<br />

衍 生 類 的 宣 告 格 式 如 下 :<br />

僱 員 類 Employee 定 義 如 下 :<br />

屬 性 類 修 飾 符 class 衍 生 類 名 : 基 類 名 { 類 體 }<br />

class Employee : Person//Person 是 基 類 類<br />

{<br />

}<br />

private string department;// 門 , 新 增 資 料 成 員 資 , 新 增 資 料 成 部<br />

private decimal salary;// 工<br />

public Employee(string Name,int Age,string D,decimal S) : base(Name,Age)<br />

員<br />

{<br />

}<br />

/* base<br />

*/<br />

的 第 一 種 用 法 , 根 據 參 數 調 用 指 定 基 類 建 構 函 數 , 注 意 參 數 的 傳 遞 意 注<br />

department = D;<br />

salary = S;<br />

public new void Display()// Display() 基 類 方 意 用 new, override 例 不 可 用 蓋 覆<br />

{<br />

}<br />

修 改 主 函 數 如 下 :<br />

class Class1<br />

{<br />

}<br />

// 注<br />

base.Display();// 存<br />

,base 的<br />

, 法<br />

Console.WriteLine(" :{1}",department,salary);<br />

類 被 覆 蓋 的 方 法 第 二 種 用 法 本<br />

門 工 資 基 部 取<br />

static void Main(string[] args)<br />

{<br />

}<br />

Employee OneEmployee = new Employee(" 李<br />

OneEmployee.Display();<br />

",30," 計 四<br />

",2000); 系<br />

機<br />

Employee 類 繼 承 了 基 類 Person 的 方 法 SetName()、SetAge(), 資 料 成 員 name 和 age, 即<br />

算<br />

認 為 基 類 Person 的 這 些 成 員 也 是 Employee 類 的 成 員 , 但 不 能 繼 承 建 構 函 數 和 解 構 函 數 。 添 加<br />

了 新 的 資 料 成 員 department 和 salary。 覆 蓋 了 方 法 Display()。 請 注 意 , 雖 然 Employee 類 繼 承<br />

了 基 類 Person 的 name 和 age, 但 由 於 它 們 是 基 類 的 私 有 成 員 ,Employee 類 中 新 增 或 覆 蓋 的 方<br />

法 不 能 直 接 修 改 name 和 age, 只 能 通 過 基 類 原 有 的 公 有 方 法 SetName() 和 SetAge() 修 改 。 如 果<br />

26


希 望 在 Employee 類 中 能 直 接 修 改 name 和 age, 必 須 在 基 類 中 修 改 它 們 的 屬 性 為 protected。<br />

1.7.2 base 關 鍵 字<br />

<br />

<br />

base 關 鍵 字 用 於 從 衍 生 類 中 存 取 基 類 成 員 , 它 有 兩 種 基 本 用 法 :<br />

在 定 義 衍 生 類 的 建 構 函 數 中 , 指 明 要 調 用 的 基 類 建 構 函 數 , 由 於 基 類 可 能 有 多 個 建 構 函<br />

數 , 根 據 base 後 的 參 數 型 別 和 個 數 , 指 明 要 調 用 哪 一 個 基 類 建 構 函 數 。 參 見 上 節 僱 員 類<br />

Employee 建 構 函 數 定 義 中 的 base 的 第 一 種 用 法 。<br />

在 衍 生 類 的 方 法 中 調 用 基 類 中 被 衍 生 類 覆 蓋 的 方 法 。 參 見 上 節 僱 員 類 Employee 的 Display()<br />

方 法 定 義 中 的 base 的 第 二 種 用 法 。<br />

1.7.3 覆 蓋 基 類 成 員<br />

在 衍 生 類 中 , 通 過 宣 告 與 基 類 完 全 相 同 新 成 員 , 可 以 覆 蓋 基 類 的 同 名 成 員 , 完 全 相 同 是 指<br />

函 數 型 別 、 函 數 名 、 參 數 型 別 和 個 數 都 相 同 。 如 上 例 中 的 方 法 Display()。 衍 生 類 覆 蓋 基 類 成 員<br />

不 算 錯 誤 , 但 會 導 致 編 譯 器 發 出 警 告 。 如 果 增 加 new 修 飾 符 , 表 示 認 可 覆 蓋 , 編 譯 器 不 再 發<br />

出 警 告 。 請 注 意 , 覆 蓋 基 類 的 同 名 成 員 , 並 不 是 移 走 基 類 成 員 , 只 是 必 須 用 如 下 格 式 存 取 基 類<br />

中 被 衍 生 類 覆 蓋 的 方 法 :base.Display()。<br />

1.7.4 C# 語 言 類 繼 承 特 點<br />

C# 語 言 類 繼 承 有 如 下 特 點 :<br />

C# 語 言 只 允 許 單 繼 承 , 即 衍 生 類 只 能 有 一 個 基 類 。<br />

C# 語 言 繼 承 是 可 以 傳 遞 的 , 如 果 C 從 B 衍 生 ,B 從 A 衍 生 , 那 麼 C 不 但 繼 承 B 的 成 員 , 還<br />

要 繼 承 A 中 的 成 員 。<br />

衍 生 類 可 以 添 加 新 成 員 , 但 不 能 刪 除 基 類 中 的 成 員 。<br />

衍 生 類 不 能 繼 承 基 類 的 建 構 函 數 、 解 構 函 數 和 事 件 。 但 能 繼 承 基 類 的 屬 性 。<br />

衍 生 類 可 以 覆 蓋 基 類 的 同 名 成 員 , 如 果 在 衍 生 類 中 覆 蓋 了 基 類 同 名 成 員 , 基 類 該 成 員 在 衍<br />

生 類 中 就 不 能 被 直 接 存 取 , 只 能 通 過 「base. 基 類 方 法 名 」 存 取 。<br />

衍 生 類 對 象 也 是 其 基 類 的 對 象 , 但 基 類 對 象 卻 不 是 其 衍 生 類 的 對 象 。 例 如 , 前 面 定 義 的 僱<br />

員 類 Employee 是 Person 類 的 衍 生 類 , 所 有 僱 員 都 是 人 類 , 但 很 多 人 並 不 是 僱 員 , 可 能<br />

是 學 生 , 自 由 職 業 者 , 兒 童 等 。 因 此 C# 語 言 規 定 , 基 類 的 參 照 變 數 可 以 引 用 其 衍 生 類 對<br />

象 , 但 衍 生 類 的 參 照 變 數 不 可 以 引 用 其 基 類 對 象 。<br />

1.8 類 的 成 員<br />

由 於 C# 程 式 中 每 個 變 數 或 函 數 都 必 須 屬 於 一 個 類 或 結 構 , 不 能 像 C 或 C++ 那 樣 建 立 全 域 變<br />

數 , 因 此 所 有 的 變 數 或 函 數 都 是 類 或 結 構 的 成 員 。 類 的 成 員 可 以 分 為 兩 大 類 : 類 本 身 所 宣 告 的<br />

27


以 及 從 基 類 中 繼 承 來 的 。<br />

1.8.1 類 的 成 員 類 型<br />

類 的 成 員 包 括 以 下 類 型 :<br />

局 部 變 數 : 在 for、switch 等 語 句 中 和 類 方 法 中 定 義 的 變 數 , 只 在 指 定 範 圍 內 有 效 。<br />

欄 位 : 即 類 中 的 變 數 或 常 數 , 包 括 靜 態 欄 位 、 實 例 欄 位 、 常 數 和 唯 讀 欄 位 。<br />

方 法 成 員 : 包 括 靜 態 方 法 和 實 例 方 法 。<br />

屬 性 : 按 屬 性 指 定 的 get 方 法 和 set 方 法 對 欄 位 進 行 讀 寫 。 屬 性 本 質 上 是 方 法 。<br />

事 件 : 代 表 事 件 本 身 , 同 時 聯 繫 事 件 和 事 件 處 理 函 數 。<br />

索 引 子 : 允 許 像 使 用 陣 列 那 樣 存 取 類 中 的 資 料 成 員 。<br />

運 算 子 多 載 : 採 用 多 載 運 算 子 的 方 式 定 義 類 中 特 有 的 操 作 。<br />

建 構 函 數 和 解 構 函 數 。<br />

包 含 有 可 執 行 程 式 碼 的 成 員 被 認 為 是 類 中 的 函 數 成 員 , 這 些 函 數 成 員 有 方 法 、 屬 性 、 索 引<br />

子 、 運 算 子 多 載 、 建 構 函 數 和 解 構 函 數 。<br />

1.8.2 類 成 員 存 取 修 飾 符<br />

存 取 修 飾 符 用 於 指 定 類 成 員 的 可 存 取 性 ,C# 存 取 修 飾 符 有 private、protected、public 和<br />

internal 四 種 。private 宣 告 私 有 成 員 , 私 有 資 料 成 員 只 能 被 類 內 部 的 函 數 使 用 和 修 改 , 私 有 函<br />

數 成 員 只 能 被 類 內 部 的 函 數 調 用 。 衍 生 類 雖 然 繼 承 了 基 類 私 有 成 員 , 但 不 能 直 接 存 取 它 們 , 只<br />

能 通 過 基 類 的 公 有 成 員 存 取 。protected 宣 告 保 護 成 員 , 保 護 資 料 成 員 只 能 被 類 內 部 和 衍 生 類<br />

的 函 數 使 用 和 修 改 , 保 護 函 數 成 員 只 能 被 類 內 部 和 衍 生 類 的 函 數 調 用 。public 宣 告 公 有 成 員 ,<br />

類 的 公 用 函 數 成 員 可 以 被 類 的 外 部 程 序 所 調 用 , 類 的 公 用 資 料 成 員 可 以 被 類 的 外 部 程 序 直 接 使<br />

用 。 公 有 函 數 實 際 是 一 個 類 和 外 部 通 訊 的 介 面 , 外 部 函 數 通 過 調 用 公 有 函 數 , 按 照 預 先 設 定 好<br />

的 方 法 修 改 類 的 私 有 成 員 和 保 護 成 員 。internal 宣 告 內 部 成 員 , 內 部 成 員 只 能 在 同 一 程 序 集 中<br />

的 文 件 中 才 是 可 以 存 取 的 , 一 般 是 同 一 個 應 用 (Application) 或 庫 (Library)。<br />

1.9 類 的 欄 位 和 屬 性<br />

類 或 結 構 中 定 義 的 變 數 和 常 數 一 般 稱 為 「 欄 位 」。 屬 性 不 是 欄 位 , 本 質 上 是 定 義 修 改 欄 位<br />

的 方 法 , 由 於 屬 性 和 欄 位 的 緊 密 關 係 , 把 它 們 放 到 一 起 敘 述 。<br />

1.9.1 靜 態 欄 位 、 實 例 欄 位 、 常 數 和 唯 讀 欄 位<br />

用 修 飾 符 static 宣 告 的 欄 位 為 靜 態 欄 位 。 不 管 包 含 該 靜 態 欄 位 的 類 生 成 多 少 個 對 象 或 根 本<br />

無 對 象 , 該 欄 位 都 只 有 一 個 實 例 , 靜 態 欄 位 不 能 被 撤 銷 。 必 須 採 用 如 下 方 式 引 用 靜 態 欄 位 : 類<br />

名 . 靜 態 欄 位 名 。 如 果 類 中 定 義 的 欄 位 不 使 用 修 飾 符 static, 該 欄 位 為 實 例 欄 位 , 每 產 生 該 類 的<br />

28


一 個 對 象 , 在 對 象 內 產 生 一 個 該 欄 位 實 例 , 產 生 它 的 對 象 被 撤 銷 , 該 欄 位 對 象 也 被 撤 銷 , 實 例<br />

欄 位 採 用 如 下 方 式 引 用 : 實 例 名 . 實 例 欄 位 名 。 用 const 修 飾 符 宣 告 的 欄 位 為 常 數 , 常 數 只 能<br />

在 宣 告 中 初 始 化 , 以 後 不 能 再 修 改 。 用 readonly 修 飾 符 宣 告 的 欄 位 為 唯 讀 欄 位 , 唯 讀 欄 位 是<br />

特 殊 的 實 例 欄 位 , 它 只 能 在 欄 位 宣 告 中 或 建 構 函 數 中 重 新 指 派 值 , 在 其 它 任 何 地 方 都 不 能 改 變<br />

唯 讀 欄 位 的 值 。 例 子 :<br />

public class Test<br />

{<br />

}<br />

public const int intMax = int.MaxValue;// 數 , 必 須 賦 初 值 例 欄 位 常<br />

public int x = 0;// 實<br />

public readonly int y = 0;// 讀 態 欄 位 唯<br />

public static int cnt = 0;// 靜<br />

public Test(int x1, int y1)// 構 函 數 建<br />

{<br />

}<br />

//intMax = 0;// 誤 , 不 能 修 改 常 數 建 構 函 數 允 許 修 改 實 例 欄 位 錯<br />

x = x1;//<br />

建 構 函 數 允 許 修 改 唯 讀 欄 位 在<br />

y = y1;//<br />

產 生 一 個 對 象 都 調 用 建 構 函 數 , 用 此 語 句 可 以 記 錄 對 象 的 個 數 在<br />

cnt++;// 每<br />

public void Modify(int x1,int y1)<br />

{<br />

}<br />

//intMax = 0;// 誤 , 不 能 修 改 常 數 錯<br />

x = x1;<br />

class Class1<br />

{<br />

}<br />

cnt = y1;<br />

//y = 10;// 允 許 修 改 唯 讀 欄 位 不<br />

static void Main(string[] args)<br />

{<br />

}<br />

Test T1 = new Test(100,200);<br />

T1.x = 40;// 引<br />

用 靜 態 欄 位 採 用 : 類 實<br />

Test.cnt = 0;//<br />

用 唯 讀 欄 位 引<br />

int z = T1.y;// 引<br />

z = Test.intMax;// 用 常 數 引<br />

. 靜 名<br />

欄 位 名 態<br />

29<br />

. 例 欄 位 採 用 : 實 例 名 例 欄 位 名 實 用


1.9.2 屬 性 (Property)<br />

C# 語 言 支 援 組 件 編 程 , 組 件 也 是 類 , 組 件 用 屬 性 、 方 法 、 事 件 描 述 。 屬 性 不 是 欄 位 , 但 必<br />

然 和 類 中 的 某 個 或 某 些 欄 位 相 聯 繫 , 屬 性 定 義 了 得 到 和 修 改 相 聯 繫 的 欄 位 的 方 法 。C# 中 的 屬 性<br />

更 充 分 地 體 現 了 對 象 的 封 裝 性 : 不 直 接 操 作 類 的 資 料 內 容 , 而 是 通 過 存 取 器 進 行 存 取 , 借 助 於<br />

get 和 set 方 法 對 屬 性 的 值 進 行 讀 寫 。 存 取 屬 性 值 的 語 法 形 式 和 存 取 一 個 變 數 基 本 一 樣 , 使 存<br />

取 屬 性 就 像 存 取 變 數 一 樣 方 便 , 符 合 習 慣 。<br />

在 類 的 基 本 概 念 一 節 中 , 定 義 一 個 描 述 個 人 情 況 的 類 Person, 其 中 欄 位 name 和 age 是 私<br />

有 欄 位 , 記 錄 姓 名 和 年 齡 , 外 部 通 過 公 有 方 法 SetName 和 SetAge 修 改 這 兩 個 私 有 欄 位 。 現 在<br />

用 屬 性 來 描 述 姓 名 和 年 齡 。 例 子 如 下 :<br />

using System;<br />

public class Person<br />

{<br />

}<br />

private string P_name = " 張<br />

";//P_name 是 私 有 欄 位 私 有 欄 位 三<br />

private int P_age = 12;//P_age<br />

的 方 法 宣 告 , 顯 示 姓 名 和 年 齡 是<br />

public void Display()// 類<br />

{<br />

}<br />

Console.WriteLine(" 姓<br />

:{0}, 年 名<br />

public string Name// Name 屬 性 義 定<br />

{<br />

}<br />

get<br />

{ return P_name; }<br />

set<br />

{ P_name = value; }<br />

public int Age// Age 屬 性 義 定<br />

{<br />

}<br />

get<br />

{ return P_age; }<br />

set<br />

{ P_age = value; }<br />

public class Test<br />

{<br />

public static void Main()<br />

齡<br />

:{1}", P_name,P_age);<br />

30


}<br />

{<br />

}<br />

Person OnePerson = new Person();<br />

OnePerson.Name = " 田<br />

string s = OnePerson.Name;// 通<br />

OnePerson.Age = 20;// 通<br />

";//value=" set 七 ", 通 過 方 法 修 改 變 方 法 得 到 變 值 過 定 義 屬 性 , 既 保 證 了 姓 名 和 年 齡 按 指 定 方 法 修 改 田 七<br />

P_Name<br />

get P_Name<br />

int x = OnePerson.Age;//<br />

數<br />

法 形 式 和 修 改 、 得 到 一 個 變 數 基 本 一 致 , 符 合 習 慣 數 過 語<br />

OnePerson.Display();<br />

在 屬 性 的 存 取 宣 告 中 , 只 有 set 存 取 器 表 明 屬 性 的 值 只 能 進 行 設 置 而 不 能 讀 出 , 只 有 get<br />

存 取 器 表 明 屬 性 的 值 是 唯 讀 的 不 能 改 寫 , 同 時 具 有 set 存 取 器 和 get 存 取 器 表 明 屬 性 的 值 的 讀<br />

寫 都 是 允 許 的 。<br />

雖 然 屬 性 和 欄 位 的 語 法 比 較 類 似 , 但 由 於 屬 性 本 質 上 是 方 法 , 因 此 不 能 把 屬 性 當 做 變 數 那<br />

樣 使 用 , 也 不 能 把 屬 性 作 為 傳 參 照 參 數 或 輸 出 參 數 來 進 行 傳 遞 。<br />

1.10 類 的 方 法<br />

方 法 是 類 中 用 於 執 行 計 算 或 其 它 行 為 的 成 員 。 所 有 方 法 都 必 須 定 義 在 類 或 結 構 中 。<br />

1.10.1 方 法 的 宣 告<br />

方 法 的 宣 告 格 式 如 下 :<br />

屬 性 方 法 修 飾 符 返 回 型 別 方 法 名 ( 形 參 列 表 ) { 方 法 體 }<br />

方 法 修 飾 符 包 括 new、public、protected、internal、private、static、virtual、sealed、override、<br />

abstract 和 extern。 這 些 修 飾 符 有 些 已 經 介 紹 過 , 其 它 修 飾 符 將 逐 一 介 紹 。 返 回 型 別 可 以 是 任<br />

何 合 法 的 C# 資 料 型 別 , 也 可 以 是 void, 即 無 返 回 值 。 形 參 列 表 的 格 式 為 :( 形 參 型 別 形 參 1, 形<br />

參 型 別 形 參 2, ...), 可 以 有 多 個 形 參 。 不 能 使 用 C 語 言 的 形 參 格 式 。<br />

1.10.2 方 法 參 數 的 種 類<br />

C# 語 言 的 方 法 可 以 使 用 如 下 四 種 參 數 ( 請 注 意 和 參 數 型 別 的 區 別 ):<br />

傳 值 參 數 , 不 含 任 何 修 飾 符 。<br />

傳 參 照 參 數 , 以 ref 修 飾 符 宣 告 。<br />

輸 出 參 數 , 以 out 修 飾 符 宣 告 。<br />

參 量 參 數 , 以 params 修 飾 符 宣 告 。<br />

1. 傳 值 參 數<br />

當 用 傳 值 參 數 向 方 法 傳 遞 參 數 時 , 程 序 複 製 實 參 的 值 , 並 且 將 此 副 本 傳 遞 給 該 方 法 , 被 調<br />

用 的 方 法 不 會 修 改 實 參 的 值 , 所 以 使 用 傳 值 參 數 時 , 可 以 保 證 實 參 的 值 是 安 全 的 。 如 果 參 數 型<br />

31


因<br />

別 是 參 照 型 別 , 例 如 是 類 的 參 照 變 數 , 則 副 本 中 儲 存 的 也 是 對 象 的 參 照 , 所 以 副 本 和 實 參 引 用<br />

同 一 個 對 象 , 通 過 這 個 副 本 , 可 以 修 改 實 參 所 引 用 的 對 象 中 的 資 料 成 員 。<br />

2. 傳 參 照 參 數<br />

有 時 在 方 法 中 , 需 要 修 改 或 得 到 方 法 外 部 的 變 數 值 ,C 語 言 是 向 方 法 傳 遞 實 參 指 標 來 達 到<br />

目 的 , 而 C# 語 言 是 用 傳 參 照 參 數 。 當 用 傳 參 照 參 數 向 方 法 傳 遞 實 參 時 , 程 序 將 把 實 參 的 參 照 ,<br />

即 實 參 在 記 憶 體 中 的 地 址 傳 遞 給 方 法 , 方 法 通 過 實 參 的 參 照 ( 地 址 ), 修 改 或 得 到 方 法 外 部 的 變<br />

數 值 。 傳 參 照 參 數 以 ref 修 飾 符 宣 告 。 注 意 在 使 用 前 , 實 參 變 數 必 須 被 設 置 初 始 值 。<br />

3. 輸 出 參 數<br />

為 了 把 方 法 的 運 算 結 果 保 存 到 外 部 變 數 , 因 此 需 要 知 道 外 部 變 數 的 參 照 ( 地 址 )。 輸 出 參 數<br />

用 於 向 方 法 傳 遞 外 部 變 數 參 照 ( 地 址 ), 所 以 輸 出 參 數 也 是 傳 參 照 參 數 , 與 傳 參 照 參 數 的 差 別 在<br />

於 調 用 方 法 前 無 需 對 變 數 進 行 初 始 化 。 在 方 法 返 回 後 , 傳 遞 的 變 數 被 認 為 經 過 了 初 始 化 。 傳 值<br />

參 數 、 傳 參 照 參 數 和 輸 出 參 數 的 用 法 見 下 例 :<br />

using System;<br />

class g{ public int a = 0; }//<br />

class Class1<br />

{<br />

public static void F1(ref char i)//<br />

{ i = 'b';}<br />

public static void<br />

定<br />

F2(char i)//<br />

{<br />

義<br />

i = 'd';}<br />

類<br />

public static void F3(out char i)//<br />

實 值 型 別 傳<br />

{<br />

參<br />

i<br />

照<br />

= 'e';}<br />

public static void F4(string s)//<br />

{ s = "xyz";}<br />

public<br />

傳<br />

static<br />

值<br />

void<br />

參<br />

F5(g<br />

數<br />

gg)//<br />

, 參 數 型 別 為<br />

串 輸<br />

{<br />

出<br />

gg.a<br />

參<br />

=<br />

數<br />

20;}<br />

public static void F6(ref string s)//<br />

{ s = "xyz";}<br />

, 數 型 別 為 照 傳<br />

static<br />

值<br />

void<br />

參<br />

Main(string[]<br />

數<br />

args)<br />

,<br />

{<br />

型 別 為 字<br />

字 串<br />

char a = 'c';<br />

為 別 型 數 參 , 數 參 照 參 傳 數 參 值 傳<br />

string s1 = "abc";<br />

F2(a);// 傳<br />

Console.WriteLine(a);//<br />

F1(ref a);// 傳<br />

Console.WriteLine(a);//a 被<br />

char j;<br />

F3(out j);// 輸<br />

函<br />

未<br />

的<br />

32<br />

a 數 , 不 能 修 改 外 部 的 參 值<br />

a<br />

c 改 , 顯 示 修 被<br />

, 參 數 數 修 改 外 部 照 參<br />

的 a<br />

值<br />

改 為 b, 顯 修<br />

示 b<br />

j 數 , 結 果 輸 出 到 外 部 變 數 參 出


:abc,<br />

:xyz,<br />

,s1<br />

}<br />

4. 參 量 參 數<br />

Console.WriteLine(j);//<br />

值 參 數 , 參 數 型 別 是 字 串 顯<br />

F4(s1);// 傳<br />

,s1 為<br />

Console.WriteLine(s1);// 示 字 顯<br />

g g1 = new g();<br />

串 參 照 變 數 不 被 修 改 字<br />

s1<br />

F5(g1);// 傳 值 參 數 , 但 實 參 是 一 個 類 參 照 型 別 變 數 串<br />

:20, 示<br />

Console.WriteLine(g1.a.ToString());//<br />

參 照 參 數 , 參 數 型 別 是 字 串 顯<br />

F6(ref s1);// 傳<br />

Console.WriteLine(s1);// 示 字 顯<br />

}<br />

改 對 象 資 料 為 字 串 參 照 變 數 修 改 修<br />

s1 被 串<br />

參 量 參 數 使 用 params 修 飾 符 , 如 果 形 參 列 中 包 含 了 參 量 參 數 , 那 麼 它 必 須 是 參 數 表 中 最<br />

後 一 個 參 數 , 參 量 參 數 只 允 許 是 一 維 陣 列 。 比 如 string[] 和 string[][] 型 別 都 可 以 作 為 參 量 型 參<br />

數 。 最 後 , 參 量 型 參 數 不 能 再 有 ref 和 out 修 飾 符 。 見 下 例 :<br />

using System;<br />

class Class1<br />

{<br />

}<br />

static void F(params int[] args)// params 參 數 , 有 修 飾 符 量 參<br />

{<br />

}<br />

Console.Write("Array contains {0} elements:", args.Length);<br />

foreach (int i in args)<br />

Console.Write(" {0}", i);<br />

Console.WriteLine();<br />

static void Main(string[] args)<br />

{<br />

}<br />

程 序 輸 出<br />

int[] a = {1, 2, 3};<br />

a 陣 列 類 參 照 變 數 為 參<br />

F(a);// 實<br />

F(10, 20, 30, 40);// F(new int[] {60, 70, 80, 90});<br />

參 為 陣 列 類 參 照 於 價 等<br />

F(new int[] {60, 70, 80, 90});//<br />

F(new 於 價 實<br />

F();// 等<br />

F(new int[] {});// 實<br />

Array contains 3 elements: 1 2 3<br />

int[] {});<br />

為 陣 列 類 參 照 , 陣 列 無 元 素 參<br />

Array contains 4 elements: 10 20 30 40<br />

Array contains 4 elements: 60 70 80 90<br />

示 e<br />

33


F(new int[,] {});// 此 用<br />

Array contains 0 elements:<br />

Array contains 0 elements:<br />

方 法 的 參 數 為 陣 列 時 也 可 以 不 使 用 params, 此 種 方 法 可 以 使 用 一 維 或 多 維 陣 列 , 見 下 例 :<br />

using System;<br />

class Class1<br />

{<br />

static void F(int[,] args)// params<br />

{<br />

Console.Write("Array contains {0} elements:", args.Length);<br />

foreach (int i in args)<br />

參 照 變 數 , 無 修<br />

Console.Write(" {0}", i);<br />

Console.WriteLine();<br />

}<br />

static void Main(string[] args)<br />

{<br />

類 列 陣 為 別 型 數 參 , 數 參 值 傳<br />

int[,] a = {{1, 2, 3}, {4, 5, 6}};<br />

F(a);// 實<br />

//F(10, 20, 30, 40);// 格 式 不 能 使 用 此<br />

F(new int[,] {{60, 70},{80, 90}});// 實<br />

//F();// 此<br />

飾<br />

}<br />

}<br />

程 序 輸 出<br />

為 陣 列 類 參 照 格 式 不 能 使 格 式 不 能 使 用<br />

Array contains 3 elements: 1 2 3 4 5 6<br />

參<br />

Array contains 4 elements: 60 70 80 90<br />

a 陣 列 類 參 照 變 數 為 參<br />

1.10.3 靜 態 方 法 和 實 例 方 法<br />

用 修 飾 符 static 宣 告 的 方 法 為 靜 態 方 法 , 不 用 修 飾 符 static 宣 告 的 方 法 為 實 例 方 法 。 不 管<br />

類 有 否 產 生 對 象 , 類 的 靜 態 方 法 都 可 以 被 使 用 , 使 用 格 式 為 : 類 名 . 靜 態 方 法 名 。 靜 態 方 法 只<br />

能 使 用 該 靜 態 方 法 所 在 類 的 靜 態 資 料 成 員 和 靜 態 方 法 。 這 是 因 為 使 用 靜 態 方 法 時 , 該 靜 態 方 法<br />

所 在 類 可 能 還 沒 有 對 象 , 即 使 有 對 象 , 由 於 用 類 名 . 靜 態 方 法 名 方 式 調 用 靜 態 方 法 , 靜 態 方 法<br />

沒 有 this 指 標 來 存 放 對 象 的 地 址 , 無 法 判 定 應 存 取 哪 個 對 象 的 資 料 成 員 。 在 類 產 生 對 象 後 ,<br />

實 例 方 法 才 能 被 使 用 , 使 用 格 式 為 : 對 象 名 . 實 例 方 法 名 。 實 例 方 法 可 以 使 用 該 方 法 所 在 類 的<br />

所 有 靜 態 成 員 和 實 例 成 員 。 例 子 如 下 :<br />

using System;<br />

public class UseMethod<br />

34


public static void StaticMethod()// 靜 位<br />

{<br />

private static int x = 0;// 靜<br />

private int y = 1;// 實<br />

{<br />

x = 10;//<br />

//y = 20;// 錯 正<br />

}<br />

public void NoStaticMethod()// 實<br />

欄 位 例 欄 態 方 法 態<br />

, 靜 態 方 法 存 取 靜 態 資 料 成 員 誤 , 靜 態 方 法 不 能 存 取 實 例 資 料 成 員 確<br />

方 法 例<br />

{<br />

x = 10;//<br />

y = 20;//<br />

}<br />

}<br />

靜 態 public class Class1<br />

正 確 , 實 例 方 法 存 取 實 例 資 料 成 員<br />

{<br />

public static void Main()<br />

{<br />

}<br />

}<br />

UseMethod m = new UseMethod();<br />

靜 態 方 法 格 式 為 : 類 用<br />

UseMethod.StaticMethod();// 使<br />

m.NoStaticMethod();// 使<br />

實<br />

靜<br />

1.10.4 方 法 的 多 載<br />

名 .<br />

. 例 方 法 格 式 為 : 對 象 名 實 用<br />

在 C# 語 言 中 , 如 果 在 同 一 個 類 中 定 義 的 函 數 名 相 同 , 而 參 數 型 別 或 參 數 個 數 不 同 , 認 為<br />

方 法 名 例 方 法 名 態<br />

是 不 相 同 的 函 數 , 僅 返 回 值 不 同 , 不 能 看 作 不 同 函 數 , 這 叫 做 函 數 的 多 載 。 前 面 Person 類 中<br />

定 義 了 多 個 建 構 函 數 就 是 多 載 的 例 子 。 在 C 語 言 中 , 若 計 算 一 個 資 料 的 絕 對 值 , 則 需 要 對 不<br />

同 資 料 型 別 求 絕 對 值 方 法 使 用 不 同 的 方 法 名 , 如 abc() 求 整 數 絕 對 值 ,labs() 求 長 整 數 絕 對 值 ,<br />

fabs() 求 浮 點 數 絕 對 值 。 而 在 C# 語 言 中 , 可 以 使 用 函 數 多 載 特 性 , 對 這 三 個 函 數 定 義 同 樣 的 函<br />

數 名 , 但 使 用 不 同 的 參 數 型 別 。 下 面 是 實 作 方 式 :<br />

using System;<br />

public class UseAbs<br />

{<br />

public int abs(int x)//<br />

{ return(x


public Complex(double x,double y)// 建 部<br />

{ return(x<br />

< >=


即<br />

, 注 號<br />

參 個<br />

號<br />

Real = x;<br />

Imag = y;<br />

}<br />

static public Complex operator – (Complex a)// 多<br />

}<br />

{ return (new Complex(–a.Real, –a.Imag)); }<br />

數<br />

static public Complex operator +(Complex a, Complex b)//<br />

載 一 元 運 算 子 負<br />

加 子 算 運 元 二 載 多<br />

{ return (new Complex(a.Real+b.Real, a.Imag+b.Imag));}<br />

public void Display()<br />

{ Console.WriteLine("{0}+({1})j", Real,Imag); }<br />

class Class1<br />

{<br />

}<br />

static void Main(string[] args)<br />

{<br />

}<br />

Complex x = new Complex(1.0, 2.0);<br />

Complex y = new Complex(3.0, 4.0);<br />

Complex z = new Complex(5.0, 7.0);<br />

x.Display();// 顯<br />

y.Display();// 顯<br />

z.Display();// 顯<br />

z = –x;// 等<br />

z.Display();// 顯<br />

z = x+y;//<br />

z.Display();// 示 顯<br />

:1+(2)j 示<br />

:3+(4)j 示<br />

:5+(7)j 示<br />

= opeator–(x)<br />

示<br />

:–1+(–2)j<br />

:4+(6)j<br />

意 1<br />

z 於 價<br />

1.10.6 this 關 鍵 字<br />

z=opeator+(x,y)<br />

每 個 類 都 可 以 有 多 個 對 象 , 例 如 定 義 Person 類 的 兩 個 對 象 :<br />

Person P1 = new Person(" 李 四 ",30);<br />

Person P2 = new Person(" 張 三 ",40);<br />

因 此 P1.Display() 應 顯 示 李 四 訊 息 ,P2.Display() 應 顯 示 張 三 訊 息 , 但 無 論 產 生 多 少 個 對 象 , 只 有<br />

一 個 方 法 Display(), 該 方 法 是 如 何 知 道 顯 示 那 個 對 象 的 訊 息 的 呢 C# 語 言 用 參 照 變 數 this 記 錄<br />

調 用 方 法 Display() 的 對 象 , 當 某 個 對 象 調 用 方 法 Display() 時 ,this 便 引 用 該 對 象 ( 記 錄 該 對 象 的<br />

地 址 )。 因 此 , 不 同 的 對 象 調 用 同 一 方 法 時 , 方 法 便 根 據 this 所 引 用 的 不 同 對 象 來 確 定 應 該 引<br />

用 哪 一 個 對 象 的 資 料 成 員 。this 是 類 中 隱 含 的 參 照 變 數 , 它 是 被 自 動 被 指 派 值 的 , 可 以 使 用 但<br />

37


不 能 被 修 改 。 例 如 :P1.Display(),this 引 用 對 象 P1, 顯 示 李 四 訊 息 。P2.Display(),this 引 用 對<br />

象 P2, 顯 示 張 三 訊 息 。<br />

1.10.7 靜 態 建 構 函 數<br />

靜 態 建 構 函 數 用 以 初 始 化 一 些 靜 態 欄 位 或 唯 讀 欄 位 。 如 果 有 必 要 , 可 以 為 類 別 宣 告 靜 態 建<br />

構 函 數 。 靜 態 建 構 函 數 的 條 件 是 : 一 個 類 別 只 能 有 一 個 、 不 可 以 有 參 數 、 不 能 存 取 實 例 成 員 ─<br />

包 括 this, 也 不 可 加 上 public 和 private 修 飾 符 。 靜 態 建 構 函 數 的 執 行 時 機 在 任 何 靜 態 成 員 被 存<br />

取 或 任 何 類 實 例 生 成 之 前 , 你 可 以 讓 形 式 完 全 相 同 的 非 靜 態 建 構 函 數 與 之 並 存 。 例 如 :<br />

class SomeClass<br />

{<br />

}<br />

public static int x;<br />

static SomeClass() // 態 建 構 函 數 靜<br />

{<br />

}<br />

x = 1;<br />

Console.WriteLine("SomeClass "); 化 始 初<br />

public SomeClass()<br />

{ Console.WriteLine(" "); } 建 構 函 數 態 靜 非<br />

public static void Foo()<br />

{ Console.WriteLine("Foo"); }<br />

class Test<br />

{<br />

}<br />

static void Main(string[] args)<br />

{<br />

}<br />

// 三 行 都 會 啟 動 靜 態 建 構 函 這<br />

SomeClass sc = new SomeClass();<br />

數<br />

SomeClass.Foo();<br />

Console.WriteLine(SomeClass.x);<br />

1.11 類 的 多 形 性<br />

在 物 件 導 向 的 系 統 中 , 多 形 性 是 一 個 非 常 重 要 的 概 念 。C# 支 援 兩 種 類 型 的 多 形 性 , 第 一 種<br />

是 編 譯 時 的 多 形 性 , 一 個 類 的 對 象 調 用 若 干 同 名 方 法 , 系 統 在 編 譯 時 , 根 據 調 用 方 法 的 實 參 型<br />

別 及 實 參 的 個 數 決 定 調 用 那 個 同 名 方 法 , 實 現 何 種 操 作 。 編 譯 時 的 多 形 性 是 通 過 方 法 多 載 來 實<br />

38


現 的 。C# 語 言 的 方 法 多 載 以 及 運 算 子 多 載 和 C++ 語 言 的 基 本 一 致 。<br />

第 二 種 是 執 行 時 的 多 形 性 , 是 在 系 統 執 行 時 , 不 同 對 象 調 用 一 個 名 字 相 同 , 參 數 的 型 別 及<br />

個 數 完 全 一 樣 的 方 法 , 會 完 成 不 同 的 操 作 。C# 執 行 時 的 多 形 性 通 過 虛 方 法 實 現 。 在 類 的 方 法 宣<br />

告 前 加 上 了 virtual 修 飾 符 , 被 稱 之 為 虛 方 法 , 反 之 為 非 虛 方 法 。C# 語 言 的 虛 方 法 和 C++ 語 言 的<br />

基 本 一 致 。 下 面 的 例 子 說 明 了 虛 方 法 與 非 虛 方 法 的 區 別 :<br />

using System;<br />

class A<br />

{<br />

}<br />

public void F()// 虛 方 法 非<br />

{ Console.Write(" A.F"); }<br />

法 方<br />

public virtual void G()// 虛<br />

{ Console.Write(" A.G"); }<br />

class B: A//A 類<br />

{<br />

}<br />

B 類 的 基 類 為<br />

new public void F()// 基 類 的 同 名 非 虛 方 法 F(), new 注 意 使 用 蓋 覆<br />

{ Console.Write(" B.F"); }<br />

基 類 的 同 名 虛 方 法 G(), 蓋<br />

public override void G()// 覆<br />

{ Console.Write(" B.G"); }<br />

class Test<br />

{<br />

}<br />

static void F2(A aA)// A , 參 數 為 意 注<br />

{ aA.G();}<br />

static void Main()<br />

{<br />

}<br />

B b = new B();<br />

A a1 = new A();<br />

基 類 參 照 變 數 引 用 衍 生 類 對 象 許<br />

A a2 = b;//<br />

A 基 類 用 允<br />

a1.F();// 調<br />

a2.F();//F() 為<br />

b.F();//F() 為<br />

a1.G();//G() 為<br />

a2.G();/*G() 為<br />

F2(b);// 實<br />

F2(a1);// 實<br />

非 虛 方 顯 基 的 非 虛 方 法 , 調 用 衍 生 的<br />

對<br />

對<br />

F(), 法<br />

引<br />

引<br />

調<br />

由<br />

意 使 注<br />

參 照 變 數 類<br />

A.F<br />

F(),<br />

F(), 的 顯 示<br />

對<br />

對<br />

,a2 引<br />

A A.F<br />

B B.F 示 類<br />

顯 類 調 aA=b,<br />

用 override<br />

B 生 類 對 衍 用<br />

的<br />

的<br />

b 象<br />

的 顯 顯<br />

*/<br />

39<br />

a1 法 , 因 方 虛<br />

A 類 基 用<br />

A 調 用 基 類 , 象<br />

G(),<br />

示 A.G<br />

a2 法 , 因 方 虛<br />

B 生 類 衍 用<br />

B 調 用 衍 生 類 , 象<br />

G(),<br />

示 B.G<br />

B 衍 生 類 為 參<br />

象 ,<br />

於 A<br />

B 生 類 衍 用<br />

G(), 數 函<br />

示 B.G<br />

A 基 類 為 參<br />

象 ,<br />

用 A<br />

G(), 數 函 的<br />

示 A.G


:{1}",name,age);<br />

那 麼 輸 出 應 該 是 :<br />

A.F A.F B.F A.G B.G B.G A.G<br />

注 意 例 子 中 , 不 同 對 象 調 用 同 名 非 虛 方 法 F() 和 同 名 虛 方 法 G() 的 區 別 。a2 雖 然 是 基 類 參 照 變<br />

數 , 但 它 引 用 衍 生 類 對 象 b。 由 於 G() 是 虛 方 法 , 因 此 a2.G() 調 用 衍 生 類 B 的 G(), 顯 示 G.F。 但<br />

由 於 F() 是 非 虛 方 法 ,a2.F() 仍 然 調 用 基 類 A 的 F(), 顯 示 A.F。 或 者 說 , 如 果 將 基 類 參 照 變 數 引<br />

用 不 同 對 象 , 或 者 是 基 類 對 象 , 或 者 是 衍 生 類 對 象 , 用 這 個 基 類 參 照 變 數 分 別 調 用 同 名 虛 方 法 ,<br />

根 據 對 象 不 同 , 會 完 成 不 同 的 操 作 。 而 非 虛 方 法 則 不 具 備 此 功 能 。<br />

方 法 F2(A aA) 中 , 參 數 是 A 類 型 別 ,F2(b) 中 形 參 和 實 參 的 關 係 是 :A aA=b, 即 基 類 參 照 變<br />

數 aA 引 用 衍 生 類 對 象 b,aA.G() 調 用 衍 生 類 B 的 函 數 G(), 顯 示 B.G。 同 理 ,F2(a1) 實 參 為 基 類 A<br />

對 象 , 調 用 A 類 的 函 數 G(), 顯 示 A.G。<br />

在 類 的 基 本 概 念 一 節 中 , 定 義 一 個 描 述 個 人 情 況 的 類 Person, 其 中 公 有 方 法 Display() 用 來<br />

顯 示 個 人 訊 息 。 在 衍 生 僱 員 類 Employee 中 , 覆 蓋 了 基 類 的 公 有 方 法 Display(), 以 顯 示 僱 員 新<br />

增 加 的 訊 息 。 我 們 希 望 隱 藏 這 些 細 節 , 希 望 無 論 基 類 還 是 衍 生 類 , 都 調 用 同 一 個 顯 示 方 法 , 根<br />

據 對 象 不 同 , 自 動 顯 示 不 同 的 訊 息 。 可 以 用 虛 方 法 來 實 現 , 這 是 一 個 典 型 的 多 形 性 例 子 。 例 子<br />

using System;<br />

public class Person<br />

{<br />

}<br />

private String name = " 張<br />

private int age = 12;<br />

";// 類 的 資 料 成 員 宣 告 三<br />

protected virtual void Display()// 的 虛 方 法 名 齡 類<br />

{ Console.WriteLine(" 姓<br />

:{0}, 年<br />

public Person(string Name, int Age)// 建<br />

{<br />

}<br />

name = Name;<br />

age = Age;<br />

}<br />

函 數 名 和 類 同 構<br />

, 函 數<br />

static public void DisplayData(Person aPerson)//<br />

Display()<br />

方 法 是 靜 態 方 法 調 用 實 例 方 法 , 如 寫 為 態 靜<br />

{ aPerson.Display(); }// 不<br />

public class Employee:Person//Person 類<br />

{<br />

private string department;<br />

private decimal salary;<br />

, 無 返 回 值 名<br />

錯<br />

是 基 類<br />

public Employee(string Name, int Age,string D, decimal S) : base(Name, Age)<br />

誤<br />

{<br />

}<br />

department = D;<br />

salary = S;<br />

40


:30<br />

:40<br />

:{0}<br />

}<br />

protected override void Display()// override 虛 方 法 , 注 意 用 載 多<br />

{<br />

}<br />

class Class1<br />

{<br />

}<br />

base.Display();// 取 基 類 同 名 方 法 門 資 存<br />

Console.WriteLine(" 部<br />

工<br />

static void Main(string[] args)<br />

{<br />

}<br />

Person OnePerson = new Person(" 李<br />

",30);<br />

Person.DisplayData(OnePerson);//<br />

",40,"<br />

示 基 類 資 料 五 顯 四<br />

:{1} ", department,salary);<br />

Employee OneEmployee = new Employee(" ",2000); 務 部 示 衍 生 類 資 料 財 王<br />

Person.DisplayData(OneEmployee); // 顯<br />

執 行 後 , 顯 示 的 效 果 是 :<br />

年<br />

門 : 財 務 部 工 資 部<br />

年<br />

:2000<br />

1.12 抽 像 類 和 抽 像 方 法<br />

抽 像 類 表 示 一 種 抽 像 的 概 念 , 只 是 希 望 以 它 為 基 類 的 衍 生 類 有 共 同 的 函 數 成 員 和 資 料 成<br />

員 。 抽 像 類 使 用 abstract 修 飾 符 , 對 抽 像 類 的 使 用 有 以 下 幾 點 規 定 :<br />

抽 像 類 只 能 作 為 其 它 類 的 基 類 , 它 不 能 直 接 被 實 例 化 。<br />

抽 像 類 允 許 包 含 抽 像 成 員 , 雖 然 這 不 是 必 須 的 。 抽 像 成 員 用 abstract 修 飾 符 修 飾 。<br />

抽 像 類 不 能 同 時 又 是 密 封 的 。<br />

抽 像 類 的 基 類 也 可 以 是 抽 像 類 。 如 果 一 個 非 抽 像 類 的 基 類 是 抽 像 類 , 則 該 類 必 須 通 過 覆 蓋<br />

來 實 現 所 有 繼 承 而 來 的 抽 像 方 法 , 包 括 其 抽 像 基 類 中 的 抽 像 方 法 , 如 果 該 抽 像 基 類 從 其 它<br />

抽 像 類 衍 生 , 還 應 包 括 其 它 抽 像 類 中 的 所 有 抽 像 方 法 。<br />

請 看 下 面 的 例 子 :<br />

abstract class Figure//<br />

{<br />

protected double x = 0, y = 0;<br />

public Figure(double a, double b)<br />

{<br />

x = a;<br />

義 定 類 像 抽<br />

, : 李 四 齡 名 姓<br />

, : 王 五 齡 名 姓<br />

41


類<br />

類<br />

}<br />

}<br />

y = b;<br />

public abstract void Area();// 像 方 法 , 無 實 作 程 式 碼 抽<br />

class Square : Figure/// Square 定<br />

{<br />

}<br />

public Square(double a, double b) : base(a, b)<br />

義<br />

{ }<br />

public override void Area()// 使 用 new, override 必 須 用 形 面 積 是 能 不<br />

{ Console.WriteLine(" 矩<br />

class Circle:Figure/// Square 定<br />

{<br />

}<br />

public Circle(double a):base(a,a)<br />

義<br />

{}<br />

public override void Area()<br />

積 是 面<br />

{ Console.WriteLine(" 圓<br />

class Class1<br />

{<br />

}<br />

static void Main(string[] args)<br />

{<br />

}<br />

Square s = new Square(20, 30);<br />

Circle c = new Circle(10);<br />

s.Area();<br />

c.Area();<br />

程 序 輸 出 結 果 為 :<br />

矩 形 面 積 是 :600<br />

圓 面 積 是 :314<br />

:{0}", x*y);}<br />

:{0}", 3.14*x*y); }<br />

抽 像 類 Figure 提 供 了 一 個 抽 像 方 法 Area(), 並 沒 有 實 現 它 , 類 Square 和 Circle 從 抽 像 類<br />

Figure 中 繼 承 方 法 Area(), 分 別 具 體 實 現 計 算 矩 形 和 圓 的 面 積 。<br />

在 類 的 基 本 概 念 一 節 中 , 定 義 一 個 描 述 個 人 情 況 的 類 Person, 它 只 是 描 述 了 一 個 人 最 一 般<br />

的 屬 性 和 行 為 , 因 此 不 希 望 生 成 它 的 對 象 , 可 以 定 義 它 為 抽 像 類 。<br />

注 意 :C++ 程 式 設 計 師 在 這 裡 最 容 易 犯 錯 誤 。C++ 中 沒 有 對 抽 像 類 進 行 直 接 宣 告 的 方 法 , 而<br />

認 為 只 要 在 類 中 定 義 了 純 虛 函 數 , 這 個 類 就 是 一 個 抽 像 類 。 純 虛 函 數 的 概 念 比 較 晦 澀 , 直 觀 上<br />

不 容 易 為 人 們 接 受 和 掌 握 , 因 此 C# 拋 棄 了 這 一 概 念 。<br />

42


1.13 密 封 類 和 密 封 方 法<br />

有 時 候 , 我 們 並 不 希 望 自 己 編 寫 的 類 被 繼 承 。 或 者 有 的 類 已 經 沒 有 再 被 繼 承 的 必 要 。C#<br />

提 出 了 一 個 密 封 類 (sealed class) 的 概 念 , 幫 助 開 發 人 員 來 解 決 這 一 問 題 。<br />

密 封 類 在 宣 告 中 使 用 sealed 修 飾 符 , 這 樣 就 可 以 防 止 該 類 被 其 它 類 繼 承 。 如 果 試 圖 將 一 個<br />

密 封 類 作 為 其 它 類 的 基 類 ,C# 編 譯 器 將 提 示 出 錯 。 理 所 當 然 , 密 封 類 不 能 同 時 又 是 抽 像 類 , 因<br />

為 抽 像 總 是 希 望 被 繼 承 的 。<br />

C# 還 提 出 了 密 封 方 法 (sealed method) 的 概 念 。 方 法 使 用 sealed 修 飾 符 , 稱 該 方 法 是 一 個 密<br />

封 方 法 。 在 衍 生 類 中 , 不 能 覆 蓋 基 類 中 的 密 封 方 法 。<br />

1.14 介 面<br />

與 類 一 樣 , 在 介 面 中 可 以 定 義 一 個 和 多 個 方 法 、 屬 性 、 索 引 子 和 事 件 。 但 與 類 不 同 的 是 ,<br />

介 面 中 僅 僅 是 它 們 的 宣 告 , 並 不 提 供 實 作 。 因 此 介 面 是 函 數 成 員 宣 告 的 集 合 。 如 果 類 或 結 構 從<br />

一 個 介 面 衍 生 , 則 這 個 類 或 結 構 負 責 實 作 該 介 面 中 所 宣 告 的 所 有 成 員 。 一 個 介 面 可 以 從 多 個 介<br />

面 繼 承 , 而 一 個 類 或 結 構 可 以 實 作 多 個 介 面 。 由 於 C# 語 言 不 支 援 多 重 繼 承 , 因 此 , 如 果 某 個<br />

類 需 要 繼 承 多 個 類 的 行 為 時 , 只 能 使 用 多 個 介 面 加 以 描 述 。<br />

1.14.1 介 面 宣 告<br />

介 面 宣 告 是 一 種 型 別 宣 告 , 它 定 義 了 一 種 新 的 介 面 型 別 。 介 面 宣 告 格 式 如 下 :<br />

屬 性 介 面 修 飾 符 interface 介 面 名 : 基 介 面 { 介 面 體 }<br />

其 中 , 關 鍵 字 interface、 介 面 名 和 介 面 體 時 必 須 的 , 其 它 項 是 可 選 的 。 介 面 修 飾 符 可 以 是 new、<br />

public、protected、internal 和 private。 例 子 :<br />

public interface IExample<br />

{<br />

//<br />

string this[int index] { get; set; }//<br />

event EventHandler E;//<br />

void F(int value);//<br />

索 引 子 宣 告 事 件 所<br />

string<br />

有<br />

P<br />

介<br />

{<br />

面<br />

get; set;}//<br />

}<br />

宣 告 介<br />

成<br />

面<br />

員<br />

時<br />

都<br />

,<br />

不<br />

需 注 意 以 下 內 容 :<br />

介 面 成 員 只 能 是 方 法 、 屬 性 、 索 引 子 和 事 件 , 不 能 是 常 數 、 欄 位 、 運 算 子 、 建 構 函 數 或 解<br />

構 函 數 , 不 能 包 含 任 何 靜 態 成 員 。<br />

能 包 括 實 作<br />

介 面 成 員 宣 告 不 能 包 含 任 何 修 飾 符 , 介 面 成 員 預 設 的 存 取 方 式 是 public。<br />

告 宣 性 屬 告 宣 法 方<br />

43


見<br />

1.14.2 介 面 的 繼 承<br />

類 似 於 類 的 繼 承 性 , 介 面 也 有 繼 承 性 。 衍 生 介 面 繼 承 了 基 介 面 中 的 函 數 成 員 說 明 。 介 面 允<br />

許 多 重 繼 承 , 一 個 衍 生 介 面 可 以 沒 有 基 介 面 , 也 可 以 有 多 個 基 介 面 。 在 介 面 宣 告 的 冒 號 後 列 出<br />

被 繼 承 的 介 面 名 字 , 多 個 介 面 名 之 間 用 分 號 分 割 。 例 子 如 下 :<br />

using System;<br />

interface IControl<br />

{ void Paint(); }<br />

interface ITextBox : IControl// Icontrol Paint() 介 面 的 方 法 了 承 繼<br />

{ void SetText(string text); }<br />

interface IListBox : IControl// Icontrol Paint()<br />

{ void SetItems(string[] items); }<br />

法 方 的 面 介 了 承 繼<br />

interface IComboBox : ITextBox, IListBox<br />

{ /* 可<br />

}<br />

上 面 的 例 子 中 , 介 面 ITextBox 和 IListBox 都 從 介 面 IControl 中 繼 承 , 也 就 繼 承 了 介 面 IControl<br />

的 Paint 方 法 。 介 面 IComboBox 從 介 面 ITextBox 和 IListBox 中 繼 承 , 因 此 它 應 該 繼 承 了 介 面<br />

ITextBox 的 SetText 方 法 和 IListBox 的 SetItems 方 法 , 還 有 IControl 的 Paint 方 法 。<br />

1.14.3 類 對 介 面 的 實 作<br />

*/ 告 新 方 法 宣 以<br />

前 面 已 經 說 過 , 介 面 定 義 不 包 括 函 數 成 員 的 實 作 部 分 。 繼 承 該 介 面 的 類 或 結 構 應 實 作 這 些<br />

函 數 成 員 。 這 裡 主 要 講 述 通 過 類 來 實 作 介 面 。 類 實 作 介 面 的 本 質 是 , 用 介 面 規 定 類 應 實 作 那 些<br />

函 數 成 員 。 用 類 來 實 作 介 面 時 , 介 面 的 名 稱 必 須 包 含 在 類 宣 告 中 的 基 類 列 表 中 。<br />

在 類 的 基 本 概 念 一 節 中 , 定 義 一 個 描 述 個 人 情 況 的 類 Person, 從 類 Person 可 以 衍 生 出 其<br />

它 類 , 例 如 : 工 人 類 、 公 務 員 類 、 醫 生 類 等 。 這 些 類 有 一 些 共 有 的 方 法 和 屬 性 , 例 如 工 資 屬 性 。<br />

一 般 希 望 所 有 衍 生 類 存 取 工 資 屬 性 時 用 同 樣 變 數 名 。 該 屬 性 定 義 在 類 Person 中 不 合 適 , 因 為<br />

有 些 人 無 工 資 , 如 小 孩 。 如 定 義 一 個 類 作 為 基 類 , 包 含 工 資 屬 性 , 但 C# 不 支 援 多 重 繼 承 。 可<br />

行 的 辦 法 是 使 用 介 面 , 在 介 面 中 宣 告 工 資 屬 性 。 工 人 類 、 公 務 員 類 、 醫 生 類 等 都 必 須 實 作 該 介<br />

面 , 也 就 保 證 了 它 們 存 取 工 資 屬 性 時 用 同 樣 變 數 名 。 例 子 如 下 :<br />

using System;<br />

public interface I_Salary// 介<br />

{<br />

}<br />

decimal Salary// 性 宣 告 屬<br />

{ get; set; }<br />

public class Person<br />

{…//<br />

屬<br />

類<br />

面<br />

44<br />

1.9.2<br />

Person 節 性<br />

義 , 這 裡 不 重 複 了 。 定


:{0}<br />

}<br />

public class Employee:Person,I_Salary//Person ,I_Salary 基 類 是 介 面 同 程 式 設 計 師 完 成 工 人 類 、 醫 生 類 等 , 定 義 工 資 變 數 名 稱 可 能 不 同 是 類<br />

{ // 不<br />

}<br />

private decimal salary;<br />

public new void Display()<br />

{<br />

}<br />

base.Display();<br />

Console.WriteLine(" ", salary); 資 工<br />

// 人 類 、 醫 生 類 等 都 要 實 現 屬 性 Salary, 保 證 使 用 的 工 資 屬 性 同 名 工<br />

public decimal Salary<br />

{<br />

}<br />

get { return salary; }<br />

set { salary = value; }<br />

public class Test<br />

{<br />

}<br />

public static void Main()<br />

{<br />

}<br />

Employee S = new Employee();<br />

";// 改 屬 七<br />

S.Name = " 田<br />

S.Age = 20;// 修<br />

改 屬 修<br />

Name 性<br />

Age<br />

S.Salary = 2000;// Salary 改 屬 性 修 性<br />

S.Display();<br />

如 果 類 實 現 了 某 個 介 面 , 類 也 隱 式 繼 承 了 該 介 面 的 所 有 基 介 面 , 不 管 這 些 基 介 面 有 沒 有 在<br />

類 宣 告 的 基 類 表 中 列 出 。 因 此 , 如 果 類 從 一 個 介 面 衍 生 , 則 這 個 類 負 責 實 現 該 介 面 及 該 介 面 的<br />

所 有 基 介 面 中 所 宣 告 的 所 有 成 員 。<br />

1.15 委 派<br />

在 這 裡 要 介 紹 的 是 C# 的 一 個 參 照 型 別 ─ 委 派 (delegate), 也 翻 譯 為 代 表 。 它 實 際 上 相 當 於<br />

C 語 言 的 函 數 指 標 。 與 指 標 不 同 的 是 C# 中 的 委 派 是 型 別 安 全 的 。 委 派 類 宣 告 格 式 如 下 :<br />

屬 性 集 修 飾 符 delegate 函 數 返 回 型 別 定 義 的 委 派 標 識 符 ( 函 數 形 參 列 表 );<br />

修 飾 符 包 括 new、public、protected、internal 和 private。 例 如 我 們 可 以 宣 告 一 個 返 回 型 別 為 int,<br />

無 參 數 的 函 數 的 委 派 MyDelegate:<br />

45


。");<br />

。");<br />

public delegate int MyDelegate();// 只<br />

宣 告 了 委 派 類 MyDelegate, 可 以 產 生 委 派 類 MyDelegate 的 對 象 , 用 這 個 對 象 去 代 表 一 個 靜 態<br />

數<br />

方 法 或 非 靜 態 的 方 法 , 所 代 表 的 方 法 必 須 為 int 型 別 , 無 參 數 。 看 下 面 的 例 子 :<br />

無<br />

using System;<br />

delegate int MyDelegate();// 告 一 個 委 派 , 注 意 宣 告 的 位 置 宣<br />

public class MyClass<br />

{<br />

}<br />

public int InstanceMethod()// 靜 態 的 方 法 , 注 意 方 法 非<br />

{<br />

}<br />

Console.WriteLine(" 用 了 非 靜 態 的 方 法 調<br />

return 0;<br />

int 型 為<br />

static public int StaticMethod()// int 方 法 , 注 意 方 法 為 態 靜<br />

{<br />

}<br />

Console.WriteLine(" 用 了 靜 態 的 方 法 調<br />

return 0;<br />

public class Test<br />

{<br />

}<br />

static public void Main ()<br />

{<br />

}<br />

, 無 參 數 別<br />

別 , 無 參 數 型<br />

MyClass p = new MyClass();<br />

/* new MyDelegate ,d InstanceMethod<br />

*/<br />

類 對 象 中 儲 存 非 靜 態 的 方 法 的 地 址 派 委 立 建 用<br />

MyDelegate d = new MyDelegate(p.InstanceMethod);// 數 是 被 委 派 的 方 法 用 非 靜 態 方 法 參<br />

d();//<br />

/* new MyDelegate ,d StaticMethod 委 派 類 對 象 中 儲 存 靜 態 的 方 法 的 地 址 立 建 用 調<br />

*/<br />

d = new MyDelegate(MyClass.StaticMethod);// 數 是 被 委 派 的 方 法 用 靜 態 方 法 參<br />

d();// 調<br />

程 序 的 輸 出 結 果 是 :<br />

代 表 返 回 型 別 為 int, 能<br />

參 數 的 函<br />

非 靜 態 的 方 法 。 調 用 了 靜 態 的 方 法 。<br />

46


1.15.1 複 合 委 派 (multicast delegate)<br />

委 派 類 的 基 類 是 MulticastDelegate, 其 建 構 函 數 必 須 有 一 個 委 派 參 數 。 一 個 複 合 委 派 可 以<br />

代 表 多 個 委 派 , 如 下 例 :<br />

using System;<br />

public delegate void GreetingDelegate(string name); // 義 一 種 委 派 型 別 定<br />

public class MulticastDelegateApp<br />

{<br />

}<br />

public static void Main()<br />

{<br />

}<br />

/* 下<br />

//GreetingDelegate delegate1 = new GreetingDelegate();<br />

GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);<br />

delegate1 = EnglishGreeting; // 此<br />

delegate1 += ChineseGreeting; //<br />

");<br />

將<br />

delegate1("Peng<br />

// 調<br />

private static void EnglishGreeting(string name)<br />

{<br />

}<br />

*/ 編 譯 錯 誤 , 委 派 的 建 構 方 法 須 有 參 數 行 會<br />

上 一 行 等 價 委 派 加 入 複 合 委 派 哥 用 委 派 與 行<br />

Console.WriteLine("Good morning, {0}!", name);<br />

private static void ChineseGreeting(string name)<br />

{<br />

}<br />

Console.WriteLine (" 早<br />

, {0}!", name); 安<br />

當 調 用 複 合 委 派 時 , 此 委 派 所 代 表 的 所 有 委 派 全 被 調 用 。 撤 銷 複 合 委 派 中 的 某 個 委 派 可 以<br />

用 -= 運 算 。<br />

1.16 事 件<br />

事 件 是 C# 語 言 內 置 的 語 法 , 可 以 定 義 和 處 理 事 件 , 為 使 用 組 件 編 程 提 供 了 良 好 的 基 礎 。<br />

1.16.1 事 件 驅 動<br />

Windows 操 作 系 統 把 用 戶 的 動 作 都 看 作 消 息 ,C# 中 稱 作 事 件 , 例 如 用 鼠 標 左 鍵 單 擊 按 鈕 ,<br />

發 出 鼠 標 單 擊 按 鈕 事 件 。Windows 操 作 系 統 負 責 統 一 管 理 所 有 的 事 件 , 把 事 件 發 送 到 各 個 執<br />

47


public event EventHandler Click;// 宣 義<br />

,Click<br />

行 程 序 。 各 個 程 序 用 事 件 處 理 函 數 響 應 事 件 , 這 種 方 法 也 叫 事 件 驅 動 。<br />

C# 語 言 使 用 組 件 編 製 Windows 應 用 程 式 。 組 件 本 質 上 是 類 。 在 組 件 類 中 , 預 先 定 義 了 該<br />

組 件 能 夠 響 應 的 事 件 , 以 及 對 應 的 事 件 函 數 , 該 事 件 發 生 , 將 自 動 調 用 自 己 的 事 件 函 數 。 例 如 ,<br />

按 鈕 類 中 定 義 了 單 擊 事 件 Click 和 單 擊 事 件 函 數 。 一 個 組 件 中 定 義 了 多 個 事 件 , 應 用 程 序 中 不<br />

必 也 沒 必 要 響 應 所 有 的 事 件 , 而 只 需 響 應 其 中 很 少 事 件 , 程 式 設 計 師 撰 寫 相 應 的 事 件 處 理 函<br />

數 , 用 來 完 成 需 要 響 應 的 事 件 所 應 完 成 的 功 能 。 現 在 的 問 題 是 , 第 一 , 如 何 把 程 式 設 計 師 撰 寫<br />

的 事 件 處 理 函 數 和 組 件 類 中 預 先 定 義 的 事 件 函 數 聯 繫 起 來 。 第 二 , 如 何 使 不 需 響 應 的 事 件 無 動<br />

作 。 這 是 本 節 要 節 的 解 決 問 題 。<br />

1.16.2 事 件 的 宣 告<br />

在 C# 中 是 利 用 複 合 委 派 ( 或 稱 委 派 鏈 ) 並 搭 配 event 修 飾 符 來 完 成 事 件 處 理 。 複 合 委 派 模 型<br />

是 屬 於 發 佈 者 / 訂 閱 者 模 式 , 也 就 是 某 個 類 會 宣 告 它 會 發 佈 的 事 件 , 任 何 其 他 類 都 可 以 訂 閱 這<br />

些 事 件 。 事 件 在 C# 中 是 委 派 類 參 照 變 數 , 有 event 修 飾 符 。 例 如 按 鈕 類 的 單 擊 事 件 , 按 鈕 是 發<br />

佈 者 , 宣 告 代 表 單 擊 事 件 的 複 合 委 派 成 員 。 實 作 按 鈕 事 件 處 理 函 數 的 類 為 訂 閱 者 , 訂 閱 者 將 處<br />

理 函 數 註 冊 到 發 佈 者 的 委 派 中 , 即 完 成 訂 閱 。 發 佈 者 發 佈 事 件 , 即 調 用 委 派 所 代 表 的 方 法 。 表<br />

示 事 件 的 委 派 型 別 , 必 須 符 合 下 列 兩 點 要 求 :<br />

1. 此 委 派 型 別 必 須 有 兩 個 參 數 , 分 別 代 表 兩 個 對 象 : 喚 起 事 件 的 發 佈 者 (publisher) 和 事 件 資 訊 。<br />

2. 其 中 第 二 個 參 數 一 定 要 衍 生 自 .NET Framework 的 EventArgs 類 。<br />

下 面 的 例 子 定 義 了 一 個 發 佈 者 :Button 組 件 ; 這 個 例 子 不 完 整 , 只 是 說 明 問 題 。 實 際 在<br />

C# 語 言 類 庫 中 已 預 先 定 義 了 Button 組 件 , 這 裡 的 程 式 碼 只 是 想 說 明 Button 組 件 中 是 如 何 定 義<br />

事 件 的 。 例 子 如 下 :<br />

public delegate void EventHandler(object sender, EventArgs e);// 告 委 派 型 別 宣<br />

//EventHandler 可<br />

public class Button : Control// 定<br />

{…// 按<br />

其<br />

sender, EventArgs e) 的<br />

組<br />

protected void OnClick(EventArgs e)// 當<br />

{<br />

}<br />

if(Click != null) // 如<br />

Click(this, e); // 執<br />

public void Reset() // 銷 所 有 訂 閱 撤<br />

{ Click = null; }<br />

}<br />

方<br />

是<br />

有 訂 閱 者 已 代 表 了 事 件 處 理 函 數 行 這 個 函 數 果<br />

在 這 個 例 子 中 , 按 鈕 單 擊 事 件 發 生 , 應 有 程 式 碼 保 證 ( 未 列 出 ) 自 動 觸 發 OnClick 方 法 。Click<br />

是 類 Button 的 一 個 事 件 , 同 時 也 是 委 派 類 EventHandler 的 參 照 變 數 , 若 Click 已 代 表 了 一 些 事<br />

件 處 理 函 數 , 這 些 函 數 為 Click 事 件 應 完 成 的 功 能 ,Click 事 件 發 生 時 , 執 行 事 件 處 理 函 數 。<br />

(object 表 沒 有 返 回 值 , 參 數 為 代 以<br />

數 函<br />

Button 個 按 鈕 類 一 義<br />

件<br />

Button 類 鈕<br />

它 成 員 定<br />

一 個 事 件 Click, 告<br />

派 類 參 照 變 數 委<br />

48<br />

OnClick 事 件 發 生 , 觸 發 擊 單<br />


1.16.3 事 件 的 預 訂 和 撤 消<br />

在 隨 後 的 例 子 中 , 我 們 宣 告 了 一 個 使 用 Button 類 的 登 錄 對 話 框 類 , 對 話 框 類 含 有 兩 個 按<br />

鈕 :OK 和 Cancel 按 鈕 。 對 話 框 是 按 鈕 事 件 的 訂 閱 者 , 程 式 碼 如 下 :<br />

對 話 框 類 宣 告 錄<br />

public class LoginDialog : Form// 登<br />

{<br />

Button OkButton;<br />

Button CancelButton;<br />

public LoginDialog()// 構 函 數 建<br />

{<br />

OkButton = new Button();// OkButton 按 鈕 對 象 立 建<br />

//Click 代<br />

方<br />

+= 的 意<br />

OkButton.Click += new EventHandler(OkButtonClick); // 閱 按 鈕 事 件 訂<br />

CancelButton = new Button();// 建<br />

CancelButton.Click += new EventHandler(CancelButtonClick); // 訂<br />

}<br />

}<br />

void OkButtonClick(object sender, EventArgs e)<br />

OkButton.Click */ 的 方 法 件 理<br />

{…/* 處<br />

件 事<br />

事<br />

}<br />

void CancelButtonClick(object sender, EventArgs e)<br />

CancelButton.Click */ 的 方 法 件 理<br />

{…/* 處<br />

事<br />

}<br />

閱 按 鈕<br />

在 例 子 中 建 立 了 Button 類 的 兩 個 實 例 , 單 擊 按 鈕 事 件 Click 通 過 如 下 語 句 和 事 件 處 理 方 法<br />

聯 繫 在 一 起 : OkButton.Click+=new EventHandler(OkButtonClick) , 該 語 句 的 意 義 是 使<br />

OkButton.Click 代 表 事 件 處 理 方 法 OkButtonClick, 這 樣 只 要 Click 事 件 被 觸 發 , 事 件 處 理 方 法<br />

OkButtonClick 就 會 被 自 動 調 用 。 撤 消 事 件 和 事 件 處 理 方 法 OkButtonClick 的 聯 繫 採 用 如 下 語 句<br />

實 現 :OkButton.Click –= new EventHandler(OkButtonClick), 這 時 ,OkButton.Click 就 不 再 代 表 事<br />

件 處 理 方 法 ,Click 事 件 被 觸 發 , 方 法 OkButtonClick 就 不 會 被 調 用 了 。 務 必 理 解 這 兩 條 語 句 的<br />

用 法 。 使 用 Visual Studio.Net 集 成 環 境 可 以 自 動 建 立 這 種 聯 繫 , 在 自 動 生 成 的 程 式 碼 中 包 括 這<br />

兩 條 語 句 。<br />

表 OkButtonClick<br />

法 , 注<br />

用 使<br />

OkButton 鈕 對 象 按 立<br />

1.17 索 引 子<br />

在 C# 語 言 中 , 陣 列 也 是 類 , 比 如 我 們 宣 告 一 個 整 數 陣 列 :int[] arr = new int[5], 實 際 上 生<br />

成 了 一 個 陣 列 類 對 象 ,arr 是 這 個 對 象 的 參 照 ( 地 址 ), 存 取 這 個 陣 列 元 素 的 方 法 是 :arr[ 下 標 ],<br />

在 陣 列 類 中 , 使 用 索 引 存 取 元 素 是 如 何 實 現 的 呢 是 否 可 以 定 義 自 己 的 類 , 用 索 引 存 取 類 中 的<br />

資 料 成 員 索 引 子 (indexer) 為 我 們 提 供 了 通 過 索 引 方 式 方 便 地 存 取 類 的 資 料 成 員 的 方 法 。<br />

49


,this<br />

名<br />

首 先 看 下 面 的 例 子 , 用 於 列 印 出 小 組 人 員 的 名 單 :<br />

using System<br />

class Team<br />

{<br />

string[] s_name = new string[2];// 定<br />

public string this[int nIndex]// 索<br />

{<br />

get// 用<br />

[ 索 名<br />

] 得 引<br />

{ return s_name[nIndex]; }<br />

set// 用<br />

[ 索 名<br />

] 修 引<br />

{ s_name[nIndex] = value; }//value 為<br />

字 串 陣 列 , 記 錄 小 組 人 員 姓 為 義<br />

函<br />

函<br />

類<br />

數<br />

引 子 宣 告<br />

類 Team<br />

對 象 的<br />

}<br />

}<br />

class Test<br />

{<br />

}<br />

象<br />

public static void Main()<br />

對<br />

{<br />

}<br />

Team t1 = new Team();<br />

t1[0] = " 張<br />

t1[1] = " 李<br />

"; 三<br />

"; 斯<br />

修 改 值 被<br />

Console.WriteLine("{0},{1}", t1[0], t1[1]);<br />

顯 示 結 果 如 下 : 張 三 , 李 斯<br />

對 象<br />

get 錄 小 組 人 員 姓 名 時 , 調 用 記 到<br />

set 錄 小 組 人 員 姓 名 時 , 調 用 記 改<br />

1.18 命 名 空 間<br />

一 個 應 用 程 序 可 能 包 含 許 多 不 同 的 部 分 , 除 了 自 己 編 製 的 程 序 之 外 , 還 要 使 用 作 業 系 統 或<br />

開 發 環 境 提 供 的 函 數 庫 、 類 庫 或 組 件 庫 , 從 軟 件 開 發 商 處 購 買 來 的 函 數 庫 、 類 庫 或 組 件 庫 , 或<br />

開 發 團 隊 中 其 它 人 編 製 的 程 序 , 等 等 。 為 了 組 織 這 些 程 式 碼 , 使 應 用 程 序 可 以 方 便 地 使 用 這 些<br />

程 式 碼 ,C# 語 言 提 出 了 命 名 空 間 的 概 念 。 命 名 空 間 是 函 數 、 類 或 組 件 的 容 器 , 把 它 們 按 類 別 放<br />

入 不 同 的 命 名 空 間 中 , 命 名 空 間 提 供 了 一 個 邏 輯 上 的 層 次 結 構 體 系 , 使 應 用 程 序 能 方 便 的 找 到<br />

所 需 程 式 碼 。 這 和 C 語 言 中 的 include 語 句 的 功 能 有 些 相 似 , 但 實 作 方 法 完 全 不 同 。<br />

1.18.1 命 名 空 間 的 宣 告<br />

用 關 鍵 字 namespace 宣 告 一 個 命 名 空 間 , 命 名 空 間 的 宣 告 可 以 是 源 文 件 using 語 句 後 的 第<br />

50


類<br />

類<br />

類<br />

在<br />

一 條 語 句 , 也 可 以 是 以 成 員 的 型 式 出 現 在 其 它 命 名 空 間 的 宣 告 之 中 , 也 就 是 說 , 在 一 個 命 名 空<br />

間 內 部 還 可 以 定 義 命 名 空 間 成 員 。 全 域 命 名 空 間 應 是 源 文 件 using 語 句 後 的 第 一 條 語 句 。 在 同<br />

一 命 名 空 間 中 , 不 允 許 出 現 同 名 命 名 空 間 成 員 或 同 名 的 類 。 在 宣 告 時 不 允 許 使 用 任 何 存 取 修 飾<br />

符 , 命 名 空 間 隱 式 地 使 用 public 修 飾 符 。 例 子 如 下 :<br />

using System;<br />

namespace N1//N1 using 域 命 名 空 間 的 名 稱 , 應 是 語 句 後 的 第 一 條 語 句 全 為<br />

{<br />

}<br />

namespace N2// N1 N2 間 的 成 員 空 名 命<br />

{<br />

}<br />

class A { void f1(){}; } // N2 名 空 間 定 義 的 類 不 應 同 名 命<br />

class B { void f2(){}; }<br />

也 可 以 採 用 非 嵌 套 的 語 法 來 實 現 以 上 命 名 空 間 :<br />

namespace N1.N2// A、B N1.N2 名 空 間 中 命 在<br />

{<br />

}<br />

class A { void f1(){}; }<br />

class B { void f2(){}; }<br />

也 可 以 採 用 如 下 格 式 :<br />

A<br />

namespace N1.N2//<br />

{<br />

}<br />

命 名 空 在<br />

class A { void f1(){}; }<br />

namespace N1.N2//<br />

{<br />

}<br />

class B { void f2(){}; }<br />

在<br />

N1.N2 間<br />

N1.N2 間<br />

中<br />

1.18.2 命 名 空 間 使 用<br />

B<br />

命 名 空<br />

如 在 程 式 中 , 需 引 用 其 它 命 名 空 間 的 類 或 函 數 等 , 可 以 使 用 語 句 using, 例 如 需 使 用 上 節<br />

定 義 的 方 法 f1() 和 f2(), 可 以 採 用 如 下 程 式 碼 :<br />

using N1.N2;<br />

class WelcomeApp<br />

{<br />

public static void Main()<br />

{<br />

51


A a=new A();<br />

a.f1();<br />

}<br />

}<br />

using N1.N2 實 際 上 是 告 訴 應 用 程 式 到 哪 裡 可 以 找 到 類 A。 請 讀 者 重 新 看 一 下 1.2.1 節 中 的<br />

例 子 。<br />

1.19 非 安 全 程 式 碼<br />

在 C 和 C++ 的 程 式 設 計 師 看 來 , 指 標 是 最 強 有 力 的 工 具 之 一 , 同 時 又 帶 來 許 多 問 題 。 因 為<br />

指 標 指 向 的 資 料 型 別 可 能 並 不 相 同 , 比 如 你 可 以 把 int 型 別 的 指 標 指 向 一 個 float 型 別 的 變 數 ,<br />

而 這 時 程 序 並 不 會 出 錯 。 如 果 你 刪 除 了 一 個 不 應 該 被 刪 除 的 指 標 , 比 如 Windows 中 指 向 主 程<br />

序 的 指 標 , 程 序 就 有 可 能 崩 潰 。 因 此 濫 用 指 標 給 程 序 帶 來 不 安 全 因 素 。 正 因 為 如 此 , 在 C# 語<br />

言 中 取 消 了 指 標 這 個 概 念 。 雖 然 不 使 用 指 標 可 以 完 成 絕 大 部 分 任 務 , 但 有 時 在 程 序 中 還 不 可 避<br />

免 的 使 用 指 標 , 例 如 調 用 Windows 操 作 系 統 的 API 函 數 , 其 參 數 可 能 是 指 標 , 所 以 在 C# 中 還<br />

允 許 使 用 指 標 , 但 必 須 宣 告 這 段 程 序 是 非 安 全 (unsafe) 的 。 可 以 指 定 一 個 方 法 是 非 安 全 的 , 例<br />

如 :unsafe void F1(int * p){…}。 可 以 指 定 一 條 語 句 是 非 安 全 的 , 例 如 :unsafe int* p2=p1; 還 可<br />

以 指 定 一 段 程 式 碼 是 非 安 全 的 , 例 如 :unsafe{ int* p2=p1; int* p3=p4;}。 在 編 譯 時 要 採 用 如 下 格<br />

式 :csc 要 編 譯 的 C# 源 程 序 /unsafe。<br />

習 題<br />

1. 從 鍵 盤 輸 入 姓 名 , 在 顯 示 器 中 顯 示 對 輸 入 姓 名 的 問 候 。( 提 示 :string 為 字 串 型 別 , 用 語 句<br />

string s=Console.ReadLine() 輸 入 姓 名 )<br />

2. 建 構 函 數 和 解 構 函 數 的 主 要 作 用 是 什 麼 它 們 各 有 什 麼 特 性 <br />

3. 定 義 點 (Point) 類 , 資 料 成 員 為 私 有 成 員 , 增 加 有 參 數 和 無 參 數 建 構 函 數 , 在 主 函 數 中 生 成<br />

點 類 對 象 , 並 用 文 字 顯 示 點 類 對 象 的 坐 標 。<br />

4. 定 義 矩 形 類 , 資 料 成 員 為 私 有 成 員 , 增 加 有 參 數 和 無 參 數 建 構 函 數 , 在 主 函 數 中 生 成 矩 形<br />

類 對 象 , 並 用 文 字 顯 示 矩 形 類 對 象 的 長 、 寬 和 矩 形 左 上 角 的 坐 標 。<br />

5. 設 計 一 個 計 數 器 類 , 統 計 鍵 入 回 車 (Return) 的 次 數 , 資 料 成 員 為 私 有 成 員 , 在 主 程 序 中 使 用<br />

此 類 統 計 鍵 入 回 車 的 次 數 。<br />

6. 說 明 實 值 型 別 和 參 照 型 別 的 區 別 , 並 和 C 語 言 相 應 型 別 比 較 。<br />

7. 定 義 點 結 構 , 在 主 函 數 中 生 成 點 結 構 變 數 , 從 鍵 盤 輸 入 點 的 位 置 , 並 重 新 顯 示 坐 標 。<br />

8. 定 義 整 數 一 維 陣 列 , 從 鍵 盤 輸 入 陣 列 元 素 數 值 後 , 用 迴 圈 語 句 顯 示 所 有 元 素 的 值 。<br />

9. 輸 入 字 串 , 將 字 串 第 一 個 字 母 和 每 個 空 格 後 的 字 母 變 為 大 寫 , 其 餘 字 母 為 小 寫 後 輸 出 。<br />

10. 輸 入 5 個 數 , 在 每 兩 個 數 之 間 增 加 3 個 空 格 後 輸 出 。<br />

11. 編 一 個 猜 數 程 序 , 程 序 設 定 一 個 1 位 十 進 制 數 , 允 許 用 戶 猜 3 次 , 錯 了 告 訴 比 設 定 數 大 還<br />

是 小 , 用 switch 語 句 實 現 。<br />

52


12. C# 語 言 for 語 句 可 以 這 樣 使 用 :for(int i; i

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!