[isTMS]課程 - GitHub Copilot實戰
 

Lab 01:不用 Agent Mode,使用 GitHub Copilot 完成程式碼重構

透過註解、Code Completion 與 Next Edit Suggestions 改寫 C# 程式

預估時間:25–35 分鐘(不含環境安裝)
使用工具:Visual Studio Code、GitHub Copilot、.NET SDK

對應影片:

Lab 情境與目標

你將從 GitHub 下載一支計算蘋果折扣價格的程式,先用 Copilot 補上香蕉與榴槤的計算。三種水果各有自己的單價及折扣,但會重複使用相同公式。

這次要保留計算結果,將共用公式移到 Fruit 類別,再讓原本的程式改用這個類別。

完成 Lab 後,你將能夠:

  • 在程式碼註解中描述需求,讓 Copilot 提供程式碼建議。
  • 判斷何時接受或拒絕建議。
  • 使用 Next Edit Suggestions 協助修改相關程式碼。
  • 執行程式,確認重構前後的結果相同。

本 Lab 的提示詞都輸入在 Program.cs 的註解中,操作重點放在編輯器內的建議功能。

Copilot 每次產生的內容可能不同。請以每一步的檢查點為準,不需要追求與影片完全相同的按鍵次數或程式碼排版。

步驟 1:準備環境

1-1. 確認工具

請先準備:

  • Visual Studio Code。
  • Git。
  • .NET 8 SDK(Repository 的目標框架為 net8.0)。
  • VS Code 的 C# 開發支援,例如 Microsoft 的 C# Dev Kit。
  • 已登入 GitHub,且能使用 GitHub Copilot 的程式碼建議功能。

在終端機執行:

git --version
dotnet --list-sdks

檢查點: 可以看到 Git 版本,以及 8.x 的 .NET SDK。若只安裝較新的 SDK,請一併確認電腦具有 .NET 8 Runtime,才能執行這個 net8.0 專案。若找不到指令,請先安裝對應工具,再重新開啟 VS Code 與終端機。

1-2. 啟用建議功能

  1. 開啟 VS Code 的 Settings(設定)。
  2. 搜尋 github.copilot.enable,確認 C# 的程式碼建議已啟用。
  3. 搜尋 github.copilot.nextEditSuggestions.enabled,啟用 Next Edit Suggestions。
  4. 開啟 C# 檔案時,確認 Copilot 沒有處於暫停建議(Snooze)的狀態。

本 Lab 會用到兩種建議:

畫面中的建議 用途 操作方式
游標旁的灰色文字(Ghost Text/Code Completion) 補上目前位置的程式碼 檢查後按 Tab 接受
下一處修改建議(Next Edit Suggestions,NES) 根據已經做出的修改,建議其他位置也如何調整 依畫面提示按 Tab 前往,再按 Tab 接受

不適合的建議可按 Esc 關閉。若 Tab 只是插入空白,請先確認畫面上真的有建議,以及游標焦點在程式碼編輯區。

功能與設定可參考 VS Code:Inline suggestions。

步驟 2:從 GitHub 取得起始專案

2-1. Clone Repository

在準備放置練習專案的位置,開啟終端機並依序執行:

git clone https://github.com/isdaviddong/HOL_Copilot_First.git
cd HOL_Copilot_First
code .

若電腦無法辨識 code 指令,請改由 VS Code 的 File → Open Folder 開啟剛才下載的 HOL_Copilot_First 資料夾。

2-2. 確認專案內容

在 VS Code 的檔案總管確認可以看到:

檔案 用途
Program.cs 本 Lab 要編輯的 C# 程式
folder.csproj Console 專案設定,目標框架為 net8.0

Repository 的起始 Program.cs 只有蘋果的計算。打開檔案確認即可,接下來直接在這份程式上操作:

//計算蘋果
double applePrice = 35; // 蘋果的價格
double appleDiscount = 0.1; // 蘋果的折扣
Console.WriteLine("蘋果折扣後價格是:" + applePrice * (1 - appleDiscount));

來源:起始 Program.cs、folder.csproj。

2-3. 執行起始程式

選擇 Terminal → New Terminal,確認終端機所在資料夾包含 folder.csproj,接著執行:

dotnet run

預期結果:

蘋果折扣後價格是:31.5

dotnet run 會建置並執行目前的專案,參考 Microsoft Learn:dotnet run。

步驟 3:用 Copilot 補上香蕉的計算

3-1. 在起始程式後面輸入註解

  1. 開啟 Program.cs,保留原本的蘋果計算程式碼。
  2. 將游標移到檔案最後,留一個空白行。
  3. 輸入下方註解,再按 Enter:
// 計算香蕉

稍候,觀察 Copilot 的灰色文字建議。確認使用的是香蕉的變數、價格 20 與折扣 0.15,再按 Tab 接受。

參考結果:

// 計算香蕉
double bananaPrice = 20;
double bananaDiscount = 0.15;
Console.WriteLine("香蕉折扣後價格是:" + bananaPrice * (1 - bananaDiscount));

如果沒有建議,可先輸入 double bananaPrice = ,停下來觀察;仍未出現時,手動補上參考程式碼,再繼續練習。

3-2. 執行並確認

儲存檔案,在終端機執行:

dotnet run

預期結果:

蘋果折扣後價格是:31.5
香蕉折扣後價格是:17

本 Lab 中,Discount = 0.1 表示減價 10%,也就是支付原價的 90%。計算公式為:

折扣後價格 = 單價 × (1 - 折扣率)

步驟 4:用註解讓 Copilot 補上榴槤的計算

對應影片:約 00:30–01:05

4-1. 輸入註解

  1. 將游標移到 Program.cs 最後一行的下一行。
  2. 留一個空白行。
  3. 輸入下方註解,再按 Enter 換行:
// 計算榴槤

這裡補上價格與折扣,讓各位學員使用一致的練習資料。

4-2. 檢查並接受建議

稍候,觀察 Copilot 是否顯示灰色文字。接受之前先確認:

  • 變數代表榴槤,沒有誤用蘋果或香蕉的變數。
  • 單價為 100,折扣率為 0.2。
  • 公式為單價乘上 1 - 折扣率。
  • 輸出的水果名稱為「榴槤」。

內容正確就按 Tab 接受。若一次只補完一部分,可繼續換行或輸入程式碼前綴,再檢查下一次建議。

參考結果:

// 計算榴槤
double durianPrice = 100;
double durianDiscount = 0.2;
Console.WriteLine("榴槤折扣後價格是:" + durianPrice * (1 - durianDiscount));

如果沒有建議,可先輸入 double durianPrice = ,停下來觀察;仍未出現時,手動補上參考程式碼,再繼續後面的練習。

4-3. 記錄重構前的結果

儲存後執行 dotnet run。

水果 單價 折扣率 預期折扣後價格
蘋果 35 0.1 31.5
香蕉 20 0.15 17
榴槤 100 0.2 80

檢查點: 三筆結果都正確。接下來的重構必須保留這些結果。

步驟 5:用提示詞產生 Fruit 類別

對應影片:約 01:05–02:39

5-1. 先想清楚要抽出什麼

觀察目前的三段程式碼:水果名稱、單價及折扣不同,但計算方式相同。

先花一分鐘,試著自己寫一句註解,說明這個類別應該有哪些資料,以及能做什麼。

5-2. 在檔案最下方加入需求

請將游標移到三段水果計算程式碼的後面,輸入:

// 一個計算水果折扣的類別,具有水果名稱、單價、折扣三個屬性,和一個計算折扣後價格的方法。

按 Enter,等待 Copilot 的建議。這就是影片示範的做法:將需求寫進程式碼註解。

若產生的名稱或計算方式不明確,可把註解補充成:

// 建立 Fruit 類別。
// Name 是 string,預設為空字串;Price 與 Discount 是 double。
// Discount 是減價比例,例如 0.1 表示減價 10%。
// GetDiscountedPrice() 回傳 Price * (1 - Discount)。

如果仍沒有建議,先輸入 class Fruit 並換行,再觀察後續補完。

5-3. 接受並檢查類別

以下是符合需求的一種寫法,先自行操作,再用它核對:

class Fruit
{
    public string Name { get; set; } = string.Empty;
    public double Price { get; set; }
    public double Discount { get; set; }

    public double GetDiscountedPrice()
    {
        return Price * (1 - Discount);
    }
}

檢查點:

  • 類別具有 Name、Price、Discount 三個屬性。
  • GetDiscountedPrice() 回傳折扣後的價格。
  • 沒有把 0.1 誤解為只支付原價的 10%。
  • Fruit 類別放在檔案最下方,所有直接執行的敘述都在類別前面。

本 Lab 使用 Console 範本的 top-level statements 寫法。請把 Console.WriteLine(...) 等直接執行的程式放在 class Fruit 前面,避免出現 CS8803。

5-4. 儲存並執行

執行 dotnet run,確認依然得到 31.5、17、80。

此時只是新增類別,上方三段程式還沒有使用它,所以還沒完成重構。

步驟 6:先把蘋果改成使用 Fruit

對應影片:約 03:15–03:52

6-1. 在蘋果的變數後面加入物件

找到這兩行:

double applePrice = 35;
double appleDiscount = 0.1;

在 appleDiscount 那行後面、原本的 Console.WriteLine 前面插入一行,開始輸入:

var apple = new Fruit

等待 Copilot 補完物件初始化內容。確認名稱、單價及折扣正確後,再按 Tab 接受。

這一步的目標:

var apple = new Fruit
{
    Name = "蘋果",
    Price = applePrice,
    Discount = appleDiscount
};

Copilot 可能把整段寫在同一行,效果相同。

6-2. 觀察下一處修改建議

接受上述修改後,觀察 Copilot 是否建議把下方原本的運算式:

applePrice * (1 - appleDiscount)

改成:

apple.GetDiscountedPrice()

如果出現 Next Edit Suggestions,依畫面提示前往該位置,確認內容後接受建議。有時第一次 Tab 是跳到建議位置,第二次才是套用修改。

如果沒有出現,手動將蘋果那行改成:

Console.WriteLine("蘋果折扣後價格是:" + apple.GetDiscountedPrice());

檢查點: 蘋果的價格已經透過 Fruit.GetDiscountedPrice() 計算,而且只輸出一次。

步驟 7:讓相同修改延伸到香蕉與榴槤

對應影片:約 03:53–04:27

7-1. 觀察 Copilot 是否提出其他修改

完成蘋果的修改後,觀察香蕉與榴槤附近是否出現建議。

如果出現,逐一檢查再接受;如果沒有,將游標移到對應折扣變數後面,開始輸入 var banana = new Fruit 或 var durian = new Fruit,讓 Copilot 接續補完。

7-2. 完成香蕉的修改

在香蕉的折扣變數後面加入物件,並替換原本的輸出敘述:

var banana = new Fruit
{
    Name = "香蕉",
    Price = bananaPrice,
    Discount = bananaDiscount
};
Console.WriteLine("香蕉折扣後價格是:" + banana.GetDiscountedPrice());

7-3. 完成榴槤的修改

同樣在榴槤的折扣變數後面加入:

var durian = new Fruit
{
    Name = "榴槤",
    Price = durianPrice,
    Discount = durianDiscount
};
Console.WriteLine("榴槤折扣後價格是:" + durian.GetDiscountedPrice());

檢查點:

  • 三種水果都各自建立了一個 Fruit 物件。
  • 三個輸出敘述都呼叫各自的 GetDiscountedPrice()。
  • 香蕉沒有誤用 applePrice,榴槤也沒有誤用其他水果的物件。
  • 原本的直接計算式已被替換,沒有多留一份舊的輸出敘述。
  • 共用公式只保留在 Fruit 類別的方法中。

步驟 8:執行並驗證重構結果

對應影片:約 04:58–05:10

8-1. 儲存並執行

儲存 Program.cs,在專案資料夾中執行:

dotnet run

預期結果:

蘋果折扣後價格是:31.5
香蕉折扣後價格是:17
榴槤折扣後價格是:80

請與步驟 4 記錄的結果比較。小數點符號可能隨電腦的地區設定不同,數值應一致。

8-2. 再做一次小修改

將:

double appleDiscount = 0.1;

暫時改成:

double appleDiscount = 0.2;

儲存並執行。蘋果應變成 28,香蕉與榴槤仍為 17、80。

這可以幫助你確認類別真的使用傳入的折扣,而不是把結果寫死。檢查完畢後,將蘋果折扣改回 0.1。

8-3. 完成確認

  • 我曾在程式碼註解中描述需求,並觀察 Copilot 的建議。
  • 我知道如何接受與關閉建議。
  • 我檢查過 AI 產生的名稱、變數與計算公式。
  • 三種水果都改為使用 Fruit 類別。
  • 重構後的輸出仍為 31.5、17、80。
  • 我修改折扣後,程式能算出正確的新結果。

常見問題

遇到的情況 處理方式
沒有灰色文字建議 確認已登入 Copilot、C# 建議已啟用,且沒有暫停建議;補上具體註解或程式碼前綴再觀察。
沒有下一處修改建議 確認 NES 設定已啟用;仍未出現就手動移到下一段,依相同方式修改。建議不一定每次都出現。
Tab 沒有接受 Copilot 建議 確認焦點在編輯器;若 IntelliSense 選單正在攔截按鍵,可先關閉選單,再確認 Copilot 建議是否仍顯示。
AI 產生不同的類別或方法名稱 可調整提示詞使用本 Lab 的名稱,或自行統一所有呼叫位置;定義與呼叫必須一致。
出現 CS8618,指出 Name 未初始化 將屬性寫成 public string Name { get; set; } = string.Empty;。
出現 CS8803 把 Fruit 類別放到檔案最後,直接執行的程式放在它前面。
dotnet run 找不到專案 確認終端機所在資料夾包含 .csproj;必要時先 cd HOL_Copilot_First。
同一種水果輸出兩次 刪除舊的 Console.WriteLine,每種水果只保留改用類別後的那一行。
計算結果不正確 檢查物件使用的變數、折扣值,以及方法是否回傳 Price * (1 - Discount)。

完整參考程式碼

完成操作後再展開核對。若卡關,也可以用這份程式碼找出差異。

展開 Program.cs 完整參考內容
// 計算蘋果
double applePrice = 35;
double appleDiscount = 0.1;
var apple = new Fruit
{
    Name = "蘋果",
    Price = applePrice,
    Discount = appleDiscount
};
Console.WriteLine("蘋果折扣後價格是:" + apple.GetDiscountedPrice());

// 計算香蕉
double bananaPrice = 20;
double bananaDiscount = 0.15;
var banana = new Fruit
{
    Name = "香蕉",
    Price = bananaPrice,
    Discount = bananaDiscount
};
Console.WriteLine("香蕉折扣後價格是:" + banana.GetDiscountedPrice());

// 計算榴槤
double durianPrice = 100;
double durianDiscount = 0.2;
var durian = new Fruit
{
    Name = "榴槤",
    Price = durianPrice,
    Discount = durianDiscount
};
Console.WriteLine("榴槤折扣後價格是:" + durian.GetDiscountedPrice());

// 共用的水果折扣計算類別
class Fruit
{
    public string Name { get; set; } = string.Empty;
    public double Price { get; set; }
    public double Discount { get; set; }

    public double GetDiscountedPrice()
    {
        return Price * (1 - Discount);
    }
}

操作後想一想

  1. 只寫「幫我建立水果類別」,和明確寫出屬性、折扣定義及方法,產生的建議有什麼差別?
  2. 在這次重構中,哪些決定由你負責?哪些修改交給 Copilot 協助?
  3. 如果 AI 產生的程式可以編譯,但折扣公式錯了,你會怎麼發現?

這次練習的重點是:你決定要怎麼改、確認 AI 的建議,再用執行結果檢查修改是否符合需求。