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