﻿# 體驗 .NET 10 的超酷新功能：dotnet run app.cs

最近微軟釋出了 .NET 10 Preview 4 版本，這個版本正式推出了一個超酷的新功能，你現在可以在完全沒有 `*.csproj` 檔案的情況下，直接使用 `dotnet run` 來執行你的 C# 程式碼！先不論這件事有沒有意義，但這個功能確實會大幅簡化我們的開發流程，讓我們可以更快速地測試和執行 C# 程式碼。今天這篇文章我們就來體驗一下這個全新功能！

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/1a3035f181ffe31f6ca4-eebf4daf-5285-47bb-900e-0875405b769d.webp)

## 🚀 什麼是 `dotnet run app.cs`？

現在你可以**直接執行單一 C# 檔案**，就像執行 Python 或 JavaScript 一樣簡單！不需要 `.csproj` 檔案，不需要複雜的專案結構，我們馬上來看一下怎樣跑？

1.  先用 Docker 或 Podman 執行 .NET 10 Preview 4 的 SDK 映像檔：
    
    ```bash
    docker run --rm -it mcr.microsoft.com/dotnet/sdk:10.0.100-preview.4-noble-amd64
    ```
    
2.  在容器內建立一個 C# 檔案 `app.cs`：
    
    以下命令會在你的 `$HOME` 目錄下建立一個名為 `app.cs` 的 C# 檔案，並寫入一個簡單的 Web API 程式碼範例：
    
    ```bash
    cat <<EOF > ~/app.cs
    #:sdk Microsoft.NET.Sdk.Web
    #:package Microsoft.AspNetCore.OpenApi@10.*-*
    
    var builder = WebApplication.CreateBuilder();
    builder.Services.AddOpenApi();
    
    var app = builder.Build();
    app.MapOpenApi();
    app.MapGet("/", () => "Hello, world!");
    
    app.Run();
    EOF
    ```
    
    > 注意: 檔名不一定要叫做 `app.cs`，你可以用任何你喜歡的名稱。
    
3.  接著在容器內執行這個 C# 檔案：
    
    ```bash
    dotnet run ~/app.cs
    ```
    
    然後一個包含 OpenAPI 規格的 Web API 站台就啟動了！
    
    ![image](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/63bb1ba90c0a1325e1ad-190fd467-716c-418a-88c1-59e15ca616ae.png)
    
4.  接著將該檔案加入執行權限並重新執行：
    
    ```bash
    chmod +x ~/app.cs
    ```
    
    ```bash
    ~/app.cs
    ```
    
    這樣就可以直接當成 C# 腳本執行了！😍
    
5.  如果想要轉成完整的 .NET 專案，只需要執行以下命令：
    
    ```bash
    cd ~
    dotnet project convert app.cs
    ```
    
    這個命令會自動：
    
    -   建立一個新的專案目錄
    -   建立一個 `app.csproj` 專案檔
    -   將 `app.cs` 搬移到專案目錄中
    -   移除所有 `#:` 與 `#!` 開頭的語法
    
    ![Image](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/a57a18fc7aa8bab98cca-7b9c1a92-c0ba-4299-9a73-dbeffbbf35d8.png)
    

### ✨ 關於 `dotnet run app.cs` 的三大亮點

我認為這個全新的功能有三大亮點：

1.  **零門檻開始**
    
    無論是新手學習、實驗、小型腳本都超方便，不需要任何專案設定檔或複雜的環境配置，而且這份 C# 原始碼還能夠跨平臺執行。
    
2.  **CLI 原生支援**
    
    執行環境只需要安裝 .NET SDK 就可以開始跑，你真的就只要有 `.cs` 檔案即可，尤其是在 Linux/macOS 環境下，真的就超方便！
    
3.  **無痛升級**
    
    程式碼長大後，可以輕鬆轉成完整專案，這樣就可以享受完整的 .NET 生態系統，包括 NuGet 套件、除錯、測試等功能。
    

### 🎯 全新的檔案層級指令

全新的 `dotnet run app.cs` 擴充了幾個**檔案層級**指令 (directive)，讓你可以更方便地管理你的 C# 腳本：

-   用 `#:package` 引用 NuGet 套件
    
    ```csharp
    #:package Humanizer@2.14.1
    
    using Humanizer;
    var dotNet9Released = DateTimeOffset.Parse("2024-12-03");
    var since = DateTimeOffset.Now - dotNet9Released;
    Console.WriteLine($"距離 .NET 9 發布已經 {since.Humanize()}");
    ```
    
-   用 `#:sdk` 指定 SDK
    
    如果要建立 Console 或 Windows Forms 應用程式，不用特別添加 `#:sdk` 指令。但你想建立 Web API 就要特別加上：
    
    ```csharp
    #:sdk Microsoft.NET.Sdk.Web
    ```
    
-   用 `#:property` 設定 MSBuild 屬性
    
    ```csharp
    #:property LangVersion preview
    ```
    
-   支援 [Shebang](https://en.wikipedia.org/wiki/Shebang_\(Unix\)) 腳本
    
    在 Unix 系統上能夠直接執行：
    
    ```csharp
    #!/usr/bin/dotnet run
    Console.WriteLine("來自 C# 腳本的問候！");
    ```
    
    但要特別注意一點，就是 [Shebang](https://en.wikipedia.org/wiki/Shebang_\(Unix\)) 不支援 Unicode 的 BOM (Byte Order Mark) 字元，所以如果你的檔案有 BOM 的話，執行時會出現問題。
    
    ```
    $ ./app.cs
    ./app.cs: line 1: #!/usr/bin/dotnet: No such file or directory
    ./app.cs: line 4: syntax error near unexpected token `('
    ./app.cs: line 4: `var builder = WebApplication.CreateBuilder();'
    ```
    

### 🔮 未來展望

微軟正在努力改善以下幾點特性：

-   [多檔案支援](https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md#multiple-c-files)
-   提供偵錯功能
-   更快的執行效能
-   VS Code 的 IntelliSense 支援

我自己是認為 Visual Studio 2022 應該不會特別支援這種類型的偵錯，也確實沒多大必要性，因為這個功能主要是針對**快速原型開發**或**小型腳本**而設計的。如果你覺得不是太重要的話，倒是可以不用太在意這個全新的特性。如果有什麼想知道的，可以到[.NET SDK 的 GitHub Repo](https://github.com/dotnet/sdk/issues) 查看問題或給予回饋！

### ⚒ 分享一個 .NET MCP 範例

我在測試這個功能時，寫了一個簡單的 MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) 範例，寫完之後覺得真的帥，一個 C# 檔案就可以完成整個 MCP 工具的開發，不但可以看到程式碼、可以隨時改，重點還不用煩惱編譯與部署的問題，在本機執行 MCP 工具超便利！

1.  首先，建立一個名為 `app.cs` 的 C# 檔案：
    
    ```bash
    mkdir -p /home/vscode/projects/echo-mcp
    touch /home/vscode/projects/echo-mcp/app.cs
    chmod +x /home/vscode/projects/echo-mcp/app.cs
    ```
    
    檔案內容如下：
    
    ```csharp
    #!/usr/bin/dotnet run
    
    #:sdk Microsoft.NET.Sdk
    #:property TargetFramework net10.0
    #:package Microsoft.Extensions.Hosting 10.*-*
    #:package ModelContextProtocol 0.2.0-preview.2
    
    using System.ComponentModel;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using ModelContextProtocol.Server;
    
    var builder = Host.CreateEmptyApplicationBuilder(settings: null);
    
    builder.Services
        .AddMcpServer()
        .WithStdioServerTransport()
        .WithToolsFromAssembly();
    
    Console.WriteLine("Starting MCP Echo Server...");
    
    await builder.Build().RunAsync();
    
    [McpServerToolType]
    public static class EchoTool
    {
        [McpServerTool, Description("Echoes the message back to the client.")]
        public static string Echo(string message) => $"Hello from C#: {message}";
    }
    ```
    
2.  提供 GitHub Copilot 一個 `.vscode/mcp.json` 設定檔
    
    ```json
    {
        "servers": {
            "echo": {
                "type": "stdio",
                "command": "/home/vscode/projects/echo-mcp/app.cs"
            }
        }
    }
    ```
    
    ![Image](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/476413d50203e67ebd49-f18e8e67-530f-431a-98e2-048c02b0a4b4.png)
    
3.  接著就可以直接從 GitHub Copilot 呼叫這個 MCP 工具了，是不是很帥！😄
    
    ![Image](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/735e5fa9feb9c7e71289-df8f3f15-cdff-4d3b-8059-c5f7f5c77a0a.png)
    

### 相關連結

-   [Announcing dotnet run app.cs - A simpler way to start with C# and .NET 10 - .NET Blog](https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/?WT.mc_id=DT-MVP-4015686)
-   [dotnet-docker/README.sdk.md at main · dotnet/dotnet-docker](https://github.com/dotnet/dotnet-docker/blob/main/README.sdk.md)
-   [sdk/documentation/general/dotnet-run-file.md at main · dotnet/sdk](https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md#multiple-c-files)
-   [Shebang (Unix) - Wikipedia](https://en.wikipedia.org/wiki/Shebang_\(Unix\))
