.NET 平台基礎
什麼是 .NET?
.NET 是微軟開發的應用程式開發平台,讓你可以用 C# 寫出各種應用程式。
💡 比喻:廚房
- .NET 平台 = 整個廚房(包含瓦斯爐、烤箱、冰箱、各種工具)
- C# 語言 = 你的廚藝(你用來做菜的技能)
- 類別庫(BCL) = 食材和調味料(現成可用的功能)
- CLR 執行環境 = 瓦斯爐(幫你把程式碼變成可執行的東西)
- 有了好廚房 + 好廚藝,就能做出各種料理(應用程式)
.NET 的演進歷史
.NET 的版本演進(不要搞混了!):
.NET Framework(2002-2019):
├── 只能在 Windows 上執行
├── 版本:1.0、2.0、3.5、4.0、4.5、4.6、4.7、4.8
├── 已經不再開發新功能(只做安全性更新)
└── 比喻:只能在一個國家使用的貨幣
.NET Core(2016-2020):
├── 跨平台!Windows、Linux、macOS 都能用
├── 版本:1.0、2.0、2.1、3.0、3.1
├── 開源、效能更好
└── 比喻:可以在全世界使用的信用卡
.NET 5+(2020-至今):統一品牌
├── 把 .NET Core 的名字簡化了(去掉 "Core")
├── .NET 5 → 6(LTS)→ 7 → 8(LTS)→ 9 → 10(LTS)
├── LTS = Long Term Support(長期支援版本,支援 3 年)
├── 偶數版本是 LTS,奇數版本只支援 18 個月
└── 比喻:每年出新手機,但只有某些型號有長期保固
現在該用哪個?
├── 新專案 → 一律用最新的 LTS 版本(目前是 .NET 8)
├── 舊專案 .NET Framework → 考慮遷移到 .NET 8
└── 千萬不要在 2024 年用 .NET Framework 開新專案!
CLR:Common Language Runtime
CLR 是 .NET 程式的執行環境,負責管理程式的執行。
比喻:虛擬機器(但不是 VM)
├── 你的 C# 程式碼不是直接在電腦上跑
├── 而是在 CLR 這個「管家」的監督下執行
├── CLR 幫你做很多事情:
│ ├── 記憶體管理(自動 GC,不用手動 free)
│ ├── 型別安全(防止存取不該存取的記憶體)
│ ├── 例外處理(try-catch 機制)
│ └── 執行緒管理
程式碼的編譯和執行流程:
C# 原始碼(.cs 檔案)
↓ C# 編譯器(Roslyn)
IL 中間語言(.dll 檔案)← 這不是機器碼!
↓ CLR 的 JIT 編譯器
機器碼(CPU 可以直接執行的指令)
↓
執行!
為什麼要有中間語言?
├── 一次編譯,到處執行(跨平台)
├── C# 編譯成 IL → IL 在不同平台上由 JIT 轉成該平台的機器碼
└── 類似 Java 的 bytecode + JVM 概念
JIT vs AOT 編譯
JIT(Just-In-Time)即時編譯:
├── 程式啟動時,CLR 才把 IL 編譯成機器碼
├── 優點:可以針對執行的硬體做優化
├── 缺點:第一次執行會比較慢(冷啟動)
├── 適合:長時間運行的伺服器應用程式
└── 比喻:現場翻譯(聽到才翻,但可以根據聽眾調整用詞)
AOT(Ahead-Of-Time)預先編譯:
├── 在發佈時就把 IL 編譯成機器碼
├── 優點:啟動速度快、檔案更小
├── 缺點:無法針對特定硬體優化、有些動態功能受限
├── .NET 8 開始支援 Native AOT
├── 適合:Lambda、CLI 工具、容器化的微服務
└── 比喻:事先翻好的翻譯稿(開場就能直接唸,但無法臨場調整)
// AOT 發佈指令
// 發佈為 Native AOT(不需要安裝 .NET Runtime)
// dotnet publish -c Release -r win-x64 --self-contained /p:PublishAot=true
// 在 .csproj 中啟用 AOT
// <PropertyGroup>
// <!-- 啟用 Native AOT 編譯 -->
// <PublishAot>true</PublishAot>
// </PropertyGroup>
// ⚠️ AOT 的限制:
// 某些依賴反射(Reflection)的功能可能不支援
// 例如:動態載入組件、某些序列化框架
// 需要使用 Source Generator 替代反射
NuGet 套件管理器
NuGet 是 .NET 的套件管理器,就像 npm(Node.js)或 pip(Python)。
比喻:應用程式商店
├── 別人寫好的功能打包成套件(Package)
├── 你透過 NuGet 下載安裝就能用
├── 不用自己從頭寫每個功能
└── 官方套件庫:nuget.org
常用的 NuGet 套件:
├── Newtonsoft.Json → JSON 處理(經典!)
├── Serilog → 日誌
├── AutoMapper → 物件對映
├── FluentValidation → 輸入驗證
├── Dapper → 輕量 ORM
├── MediatR → 中介者模式
└── Polly → 重試和斷路器
// NuGet 套件管理指令
// 安裝套件
// dotnet add package Serilog.AspNetCore
// 安裝特定版本
// dotnet add package Serilog.AspNetCore --version 8.0.0
// 移除套件
// dotnet remove package Serilog.AspNetCore
// 列出已安裝的套件
// dotnet list package
// 更新套件
// dotnet add package Serilog.AspNetCore(會自動安裝最新版)
// 還原套件(從 .csproj 中的紀錄還原所有套件)
// dotnet restore
.csproj 檔案結構
<!-- .csproj 是專案的設定檔,告訴 .NET 如何建置你的專案 -->
<Project Sdk="Microsoft.NET.Sdk.Web">
<!-- 目標框架和基本設定 -->
<PropertyGroup>
<!-- 使用 .NET 8 -->
<TargetFramework>net8.0</TargetFramework>
<!-- 啟用 Nullable Reference Types(幫你抓空值錯誤) -->
<Nullable>enable</Nullable>
<!-- 啟用隱式 using(自動 using 常用命名空間) -->
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<!-- NuGet 套件參考 -->
<ItemGroup>
<!-- 安裝的套件會列在這裡 -->
<PackageReference Include="Serilog.AspNetCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
</ItemGroup>
<!-- 專案參考(參考同一方案中的其他專案) -->
<ItemGroup>
<ProjectReference Include="..\MyApp.Core\MyApp.Core.csproj" />
</ItemGroup>
</Project>
<!-- 常見的 SDK 類型:
Microsoft.NET.Sdk → 一般類別庫、Console App
Microsoft.NET.Sdk.Web → ASP.NET Core Web 應用
Microsoft.NET.Sdk.Worker → 背景服務
-->
SDK vs Runtime
SDK 和 Runtime 的差別:
SDK(Software Development Kit):開發工具包
├── 包含編譯器、CLI 工具、專案模板
├── 用來「開發」程式
├── 比喻:完整的工具箱(鐵鎚、螺絲起子、電鑽都有)
└── 開發者的電腦必須安裝
Runtime(執行環境):
├── 只包含執行程式所需的最小元件
├── 用來「執行」程式
├── 比喻:只有鑰匙(只能開門,不能修門)
└── 伺服器只需要安裝 Runtime
三種 Runtime:
├── .NET Runtime → 基本的 CLR + BCL
├── ASP.NET Core Runtime → 加上 Web 伺服器功能
└── .NET Desktop Runtime → 加上 WPF/WinForms(桌面應用)
檢查已安裝的版本:
├── dotnet --list-sdks → 列出已安裝的 SDK
├── dotnet --list-runtimes → 列出已安裝的 Runtime
└── dotnet --version → 目前使用的 SDK 版本
dotnet CLI 常用指令
// dotnet CLI 是 .NET 的命令列工具,開發的日常必備
// 1. dotnet new:建立新專案
// 建立一個 Web API 專案
// dotnet new webapi -n MyApi
// 建立一個 Console 專案
// dotnet new console -n MyConsoleApp
// 建立一個類別庫
// dotnet new classlib -n MyLibrary
// 列出所有可用的模板
// dotnet new list
// 2. dotnet build:編譯專案
// 在專案目錄中執行
// dotnet build
// 指定 Release 模式(正式環境用)
// dotnet build -c Release
// 3. dotnet run:編譯並執行
// 開發時最常用
// dotnet run
// 指定環境變數
// dotnet run --environment Development
// 4. dotnet publish:發佈(準備部署)
// 發佈為 Release 模式
// dotnet publish -c Release -o ./publish
// 發佈為獨立部署(不需要安裝 Runtime)
// dotnet publish -c Release -r linux-x64 --self-contained
// 5. dotnet test:執行測試
// 執行所有單元測試
// dotnet test
// 產生測試覆蓋率報告
// dotnet test --collect:"XPlat Code Coverage"
// 6. 其他常用指令
// dotnet restore:還原 NuGet 套件
// dotnet clean:清除編譯輸出
// dotnet watch run:檔案修改時自動重新編譯執行(開發超方便!)
// dotnet ef migrations add Init:EF Core 資料庫遷移
指令速查表:
指令 用途 常用參數
──────────────────────────────────────────────────────────
dotnet new 建立新專案 -n(名稱)、--no-https
dotnet build 編譯 -c Release
dotnet run 編譯並執行 --urls http://localhost:5000
dotnet publish 發佈 -c Release、-o ./publish
dotnet test 執行測試 --filter "ClassName"
dotnet watch run 監看模式執行 --no-hot-reload
dotnet add package 安裝 NuGet 套件 --version 8.0.0
dotnet ef Entity Framework 指令 migrations、database
🤔 我這樣寫為什麼會錯?
❌ 錯誤 1:混用 .NET Framework 和 .NET Core 的套件
// ❌ 錯誤:在 .NET 8 專案中安裝 .NET Framework 專用的套件
// 例如:System.Web(這是 .NET Framework 專用的)
// dotnet add package System.Web ← 在 .NET 8 中不能用!
// 常見的 .NET Framework 專用命名空間(不能在 .NET 8 中使用):
// System.Web → 改用 Microsoft.AspNetCore.*
// System.Web.Http → 改用 Microsoft.AspNetCore.Mvc
// System.Configuration → 改用 Microsoft.Extensions.Configuration
// ✅ 正確:確認套件支援的框架版本
// 在 nuget.org 上查看套件的「Frameworks」標籤
// 選擇支援 net8.0 或 netstandard2.0 的版本
// 比喻:
// .NET Framework 的套件 = 只能在 110V 國家用的電器
// .NET 8 的套件 = 國際通用電壓的電器
// 插錯電壓會燒壞!
❌ 錯誤 2:用錯 SDK 版本導致編譯失敗
❌ 常見錯誤訊息:
"The current .NET SDK does not support targeting .NET 8.0"
原因:你的電腦安裝的 SDK 版本太舊
├── 專案設定 <TargetFramework>net8.0</TargetFramework>
├── 但你的 SDK 只有 .NET 6 的版本
└── 就像用 Word 2010 開 Word 2024 的檔案,格式不支援
✅ 解決方式:
1. 檢查目前 SDK 版本
dotnet --version
2. 去官網下載對應版本的 SDK
https://dotnet.microsoft.com/download
3. 如果團隊要統一版本,可以用 global.json
// global.json:鎖定專案使用的 SDK 版本
{
// 指定要使用的 SDK 版本
"sdk": {
// 使用 8.0.100 版本的 SDK
"version": "8.0.100",
// rollForward 決定找不到指定版本時怎麼辦
// latestPatch:允許使用同一個 minor 版本的最新 patch
"rollForward": "latestPatch"
}
}
// 把 global.json 放在方案根目錄
// 這樣所有團隊成員都會用同一個版本的 SDK
❌ 錯誤 3:發佈時忘記考慮部署環境
❌ 錯誤:直接把 Debug 版本丟到伺服器上
Debug vs Release 模式的差別:
├── Debug:
│ ├── 沒有最佳化(程式碼可讀性高,方便除錯)
│ ├── 包含除錯符號(.pdb 檔案)
│ ├── 效能較差
│ └── 適合:開發時使用
├── Release:
│ ├── 有最佳化(編譯器會自動優化程式碼)
│ ├── 移除除錯資訊
│ ├── 效能較好(可能差 2-5 倍)
│ └── 適合:正式環境
└── 永遠用 Release 模式發佈到正式環境!
✅ 正確的發佈指令:
├── dotnet publish -c Release
├── 或在 CI/CD 管線中設定 -c Release
└── 確認 appsettings.json 中的環境設定正確
💡 重點整理
| 概念 | 說明 |
|---|---|
| .NET Framework | 舊版,只支援 Windows,不建議新專案使用 |
| .NET 8 (LTS) | 最新的長期支援版本,跨平台 |
| CLR | 程式的執行環境,管理記憶體、型別安全 |
| JIT | 執行時才編譯,可針對硬體最佳化 |
| AOT | 發佈時預先編譯,啟動更快 |
| NuGet | .NET 的套件管理器,類似 npm |
| .csproj | 專案設定檔,定義框架版本和套件 |
| SDK vs Runtime | SDK 用來開發,Runtime 用來執行 |
| dotnet CLI | 命令列工具:new、build、run、publish、test |