Day 2 我們建立了第一個 C# Console Project,並成功執行:
Console.WriteLine("Hello, C#");
我們已經知道怎麼:
建立 Project
↓
修改 Program.cs
↓
dotnet run
↓
看到執行結果
今天不急著學新的 C# 語法,而是先回頭看看昨天建立的 Project。
今天的核心:理解一個 C# Project 是怎麼組成,以及 .NET CLI 如何將程式碼建置並執行。
建立 Console Project 後,最基本的結構如下:
Day03
├── Day03.csproj
└── Program.cs
執行過:
dotnet build
或:
dotnet run
之後,通常還會看到:
Day03
├── bin/
├── obj/
├── Day03.csproj
└── Program.cs
這些檔案與資料夾各自有不同用途:
| 項目 | 用途 |
|---|---|
Program.cs |
目前 Console Project 主要撰寫程式碼的地方 |
Day03.csproj |
Project 的設定檔 |
bin/ |
Build 完成後的輸出檔案 |
obj/ |
Build 過程使用的中間檔案 |
平常開發時,我們主要會修改:
.cs
.csproj
而 bin/、obj/ 通常由 .NET Build 系統自動管理,不需要手動修改。
.csproj.csproj 是 C# 的 Project File。
它的用途是:
描述這個 Project 要如何建立、編譯與執行。
打開 Day03.csproj,通常可以看到:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
目前先認識幾個常見設定。
OutputType<OutputType>Exe</OutputType>
表示這個 Project 會建立成可以執行的 Application。
我們目前建立的是 Console Application,因此設定為:
Exe
可以先理解成:
這個 Project 最後是要拿來執行的。
TargetFramework<TargetFramework>net10.0</TargetFramework>
代表這個 Project 的目標 Framework 是:
.NET 10
未來也可能看到:
net8.0
net9.0
net10.0
目前只要先記住:
net10.0
↓
這個 Project 以 .NET 10 為目標
ImplicitUsings<ImplicitUsings>enable</ImplicitUsings>
代表啟用部分常用 Namespace 的自動匯入。
因此我們可以直接寫:
Console.WriteLine("Hello, C#");
而不一定需要自己加入:
using System;
這不代表 System 不存在,而是 Project 幫我們自動匯入部分常用 Namespace。
Nullable<Nullable>enable</Nullable>
代表啟用 Nullable Reference Types。
它可以協助我們在編譯階段發現一些可能發生的 null 問題。
Nullable Reference Types 會在後面的文章正式介紹,目前先知道它是 Project 的一項設定即可。
Program.csProgram.cs 是目前 Console Project 主要撰寫與執行程式碼的地方。
例如:
Console.WriteLine("Hello, C#");
執行:
dotnet run
就會看到:
Hello, C#
但如果你曾經看過較早期的 C# 教學,可能會看到另一種寫法:
using System;
namespace Day03
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, C#");
}
}
}
現在建立的 Console Project 卻只有:
Console.WriteLine("Hello, C#");
原因就是現代 C# 支援:
Top-level Statements
傳統 Console Application 通常會透過:
static void Main(string[] args)
作為程式的 Entry Point(進入點)。
例如:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, C#");
}
}
程式啟動後,會從 Main() 開始執行。
現代 C# 支援 Top-level Statements,因此可以直接寫:
Console.WriteLine("Hello, C#");
不需要自己撰寫:
class Program
{
static void Main(string[] args)
{
}
}
可以簡單理解成:
傳統寫法
Program
↓
Main()
↓
程式內容
Top-level Statements
直接撰寫程式內容
但有一個重要觀念:
Top-level Statements 並不是讓程式沒有進入點,而是不需要我們自己撰寫固定的
Program與Main()結構。
編譯器會幫我們處理程式執行需要的 Entry Point。
因此目前可以把 Program.cs 簡單理解成:
Console Application 啟動後主要執行程式碼的地方。
現代 .NET Console Template 預設使用 Top-level Statements,因此這個系列也會採用這種寫法。
剛才傳統寫法中還出現:
namespace Day03
{
}
Namespace 主要用來:
組織與區分程式中的型別。
例如未來可能會有:
namespace Trading.Models;
public class Order
{
}
以及:
namespace Trading.Services;
public class OrderService
{
}
可以用概念上的階層理解:
Trading
├── Models
│ └── Order
└── Services
└── OrderService
目前還沒有正式學習 Class,所以先知道:
Namespace 用來組織與區分程式中的型別。
之後開始建立自己的 Class 時會再次深入介紹。
Day 2 我們已經使用過:
dotnet new console -n Day02
dotnet run
這些 dotnet 指令都屬於 .NET CLI。
CLI 全名是:
Command-Line Interface
也就是:
透過 Terminal 指令操作 .NET Project 的工具。
目前先認識三個最常使用的指令:
dotnet new
dotnet build
dotnet run
可以先記成:
new
↓
建立
build
↓
建置
run
↓
執行
dotnet new:建立 Projectdotnet new 用來根據 Template 建立新的 .NET Project。
例如:
dotnet new console -n Day03
可以拆成:
dotnet
↓
使用 .NET CLI
new
↓
建立新的內容
console
↓
使用 Console Application Template
-n Day03
↓
Project 名稱設定為 Day03
整句就是:
使用 Console Application Template 建立一個名稱為
Day03的 Project。
如果想查看目前有哪些 Template,可以使用:
dotnet new list
未來進入 ASP.NET Core 時,也會使用:
dotnet new webapi
建立 Web API Project。
dotnet build:建置 Project接著來看:
dotnet build
Build 可以先理解成:
將目前的 Project 編譯並建置成後續可以執行的程式產物。
假設 Program.cs:
Console.WriteLine("Hello, C#");
執行:
dotnet build
如果成功,Terminal 會看到類似:
Build succeeded.
同時 Project 中通常會產生:
Day03
├── bin/
├── obj/
├── Day03.csproj
└── Program.cs
bin 與 obj 是什麼?Build 過程中最常看到的兩個資料夾:
bin/
obj/
bin/bin 主要存放:
Build 完成後的輸出結果。
例如:
bin/
└── Debug/
└── net10.0/
obj/obj 主要存放:
Build 過程需要使用的中間檔案。
一般開發時不需要手動修改。
可以先記成:
Source Code
↓
Build
↓
obj:Build 過程的中間資料
↓
bin:Build 完成後的輸出
進入:
bin/Debug/net10.0/
可能會看到:
bin/
└── Debug/
└── net10.0/
├── Day03.dll
├── Day03.exe
├── Day03.deps.json
└── Day03.runtimeconfig.json
不同作業系統看到的檔案可能略有差異。
目前最值得注意的是:
Day03.dll
它是 Project Build 後產生的主要 .NET Assembly,包含編譯後的程式內容。
因此可以把 Build 流程先理解成:
Program.cs
↓
dotnet build
↓
編譯與建置
↓
bin/Debug/net10.0/
↓
Day03.dll
所以 dotnet build 不只是檢查程式有沒有錯,它還會真正產生後續可以執行的程式產物。
既然已經 Build 完成,也可以直接執行產生的 .dll:
dotnet ./bin/Debug/net10.0/Day03.dll
假設 Program.cs:
Console.WriteLine("Hello, C#");
會看到:
Hello, C#
整個流程可以理解成:
C# Source Code
↓
dotnet build
↓
Build Output
↓
Day03.dll
↓
dotnet Day03.dll
↓
執行程式
dotnet run:執行 Project開發時如果每次都要:
dotnet build
dotnet ./bin/Debug/net10.0/Day03.dll
會比較麻煩。
因此可以直接使用:
dotnet run
dotnet run 主要用途是:
執行目前的 Project,需要時會先進行建置。
例如:
Console.WriteLine("Hello, C#");
執行:
dotnet run
就會看到:
Hello, C#
build 與 run 的差別| 指令 | 用途 |
|---|---|
dotnet build |
編譯並建置 Project,產生 Build Output |
dotnet run |
執行目前的 Project,需要時先完成建置 |
可以簡單記成:
dotnet build
↓
我要把 Project 建置出來
dotnet run
↓
我要直接執行 Project
建立新的 Console Project:
dotnet new console -n Day03Practice
進入 Project:
cd Day03Practice
將 Program.cs 修改成:
var price = 120;
var quantity = 5;
var total = price * quantity;
Console.WriteLine(total);
目前還不需要深入理解 var,下一篇會正式介紹變數與型別。
執行結果應該是:
600
接著完成以下操作:
dotnet build 建置 Project。bin/Debug/net10.0/。Day03Practice.dll。dotnet ./bin/Debug/net10.0/Day03Practice.dll
再使用:
dotnet run
比較兩種方式的差異。
| 概念 | 用途 |
|---|---|
Program.cs |
Console Project 主要的程式執行流程 |
.csproj |
描述 Project 的設定 |
| Top-level Statements | 省略手動撰寫 Program 與 Main() 的固定結構 |
| Namespace | 組織與區分程式中的型別 |
bin/ |
Build 完成後的輸出 |
obj/ |
Build 過程的中間資料 |
dotnet new |
建立 Project |
dotnet build |
編譯並建置 Project |
dotnet run |
執行 Project |