浏览器不支持(未启用)JavaScript,本页面的某些功能无法正常使用

Csharp 14 与 DotNET 10 的杀手级特性:成为并超越脚本语言

Divider Line

当我首次在控制台运行 dotnet run my-app.cs 时,产生了一种久违的兴奋感,C# & .NET 这个传统上被视为笨重的编程语言与开发平台,突然拥有了脚本语言的灵魂。不再需要繁琐的 .csproj 文件,不再需要复杂的项目结构,一个 .cs 文件就能完整表达所有意图。这在开发体验上是非常不同的,更是 C# 生态的一次重要突破。

为此,我创建了一个开源项目 CsharpFileScripts,专门探索这项技术的创新边界。今天,我想系统性地分享这项技术,以及它为什么值得你尝试。

什么是基于文件的 C# 程序?

File-based C# Programs 是 C# 14 与 .NET 10 引入的革命性特性,允许将整个程序封装在单个 .cs 文件中,无需项目文件即可直接编译运行。

#:package Colorful.Console@1.2.15

Colorful.Console.WriteAscii("Hello, File-based C#!");

保存为 hello.cs,终端执行 dotnet run hello.cs 即可看到华丽的 ASCII 艺术字输出。就是这么简单。

核心特性深度解析

1. 顶级语句:脚本化的语法基础

这是 C# 9 引入的特性,但在基于文件的程序中,它的价值被发挥到了极致。它允许我们省略 Program 类和 Main 方法,直接从文件的第一行开始写逻辑——这正是 Python 或 JavaScript 开发者最熟悉的体验。

传统 C# (繁琐):

using System;

namespace MyApp 
{
    class Program 
    {
        static void Main(string[] args) 
        {
            Console.WriteLine("Hello World");
        }
    }
}

现代 C# 脚本 (清爽):

Console.WriteLine("Hello World");

这种语法糖不仅减少了视觉干扰,还带来两个脚本编写中极重要的便利:

  1. 全局 args:命令行参数 args 变量默认可用,无需声明。
  2. 直接 await:隐式支持异步入口,你可以直接在顶层写 await HttpClient.GetAsync(...),无需为了异步操作专门包裹一个 MainAsync

2. 预处理器指令:在代码中定义项目

这是整个特性的技术基石。如果说顶级语句则赋予了它“脚本”的形态,预处理器指令赋予了单文件“项目”的能力。C# 编译器会忽略以 #: 开头的指令,但构建系统会解析它们生成临时的 .csproj。这巧妙地在保持语言纯净性的同时,赋予了单文件脚本定义完整项目能力:

#:sdk - SDK 指定

#:sdk Microsoft.NET.Sdk.Web           // Web 应用
#:sdk Aspire.AppHost.Sdk@9.4.1        // 支持指定版本

第一行对应 <Project Sdk="...">,后续行对应 <Sdk Name="..." Version="..." />

#:property - MSBuild 属性

#:property TargetFramework=net10.0
#:property LangVersion=preview
#:property PublishAot=false  // 设置为 true 可编译为原生二进制

任何传统项目中可用的 MSBuild 属性都支持,包括条件编译符号、输出路径等。

#:package - NuGet 包引用

#:package System.CommandLine@2.0.0-*
#:package Newtonsoft.Json@13.0.3

支持版本通配符和预发布版本,语法简洁直观。

#:project - 项目引用

#:project ../ClassLib/ClassLib.csproj
#:project ../AnotherProject           // 自动查找 .csproj

这项功能让单文件程序可以无缝融入现有解决方案架构。

3. Shebang 支持:Unix 系统的原生脚本体验

在 Linux/macOS 上,C# 文件可以直接作为可执行脚本:

#!/usr/bin/env dotnet
Console.WriteLine("I'm a real shell script now!");

赋予执行权限后:

chmod +x script.cs
./script.cs arg1 arg2

构建系统甚至支持无扩展名的文件(如 ./deploy),只需这样写:

#!/usr/bin/env dotnet
#:sdk Microsoft.NET.Sdk
// ... 你的代码

4. 命令行参数与标准输入

可以通过预定义的 args 变量接收参数:

if (args.Length > 0)
{
    Console.WriteLine($"参数: {string.Join(' ', args)}");
}

推荐使用 -- 明确分隔参数,避免与 dotnet CLI 冲突:

dotnet run app.cs -- --my-option=value input.txt

标准输入处理同样简洁:

while (Console.ReadLine() is string line && line.Length > 0)
{
    ProcessLine(line);
}

5. 缓存机制

首次运行时,dotnet 主机会:

  1. 在临时目录生成可执行文件
  • Windows: %TEMP%\dotnet\runfile\
  • Linux/macOS: ~/.dotnet/runfile/
  1. 后续执行时,仅当源文件变更才重新构建
  2. 缓存不会自动清理,可通过 dotnet clean your-file.cs 手动清除

这种机制让脚本在保持快速启动的同时,避免了重复编译的开销。

项目实战:从演示看创新可能

在我的 CsharpFileScripts 项目中,我探索了这项技术的多个创新应用场景:

场景 1:单文件 Web 应用与动态文档生成

这是我个人最喜欢的演示之一——HelloTutorial.cs。它将 Markdown 文档实时转换为美观的单页 HTML 教程,完整实现了语法高亮、响应式布局,带简单交互功能。

HelloTutorial 演示

关键代码片段:

#:sdk Microsoft.NET.Sdk.Web
#:package Markdig@0.34.0
#:package PrismDownloader@1.0.0

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => Results.Content("""
    <!DOCTYPE html>
    <form>
        <textarea name="markdown" placeholder="输入 Markdown">...</textarea>
        <button>生成教程</button>
    </form>
    """, "text/html"));

运行 dotnet run HelloTutorial.cs,一个功能完整的 Web 服务器立即启动。这种轻量级模式非常适合:

  • 技术文档的快速预览
  • 本地工具的内置帮助系统
  • 轻量化内容管理系统

场景 2:交互式简历生成器

HelloVitae.cs 展示了如何将静态简历变为可交互的 Web 体验。无需部署复杂网站,运行脚本即可在本地展示个人主页。

交互式简历

场景 3:桌面自动化 RPA

HelloWindowsNotePad.cs 演示了如何调用 Windows API 实现机器人流程自动化,自动操作记事本完成文本输入、菜单操作等任务。这对系统管理员来说是极具价值的轻量级自动化方案。

场景 4:智能文件整理工具

SmartMusicOrganizer.cs 是一个实用的控制台应用,自动扫描音乐文件并按元数据分类整理。它展示了单文件程序作为系统管理工具的便捷性——复制到目标目录即可运行,无需安装。

音乐整理工具

与其他脚本语言的对比

让我们客观比较基于文件的 C# 与其他脚本方案:

特性 基于文件的 C# Python Node.js PowerShell Bash
类型安全 ✅ 强类型编译时检查 ⚠️ 运行时检查 ⚠️ 运行时检查 ⚠️ 运行时检查 ❌ 无
性能 ✅ JIT/AOT 编译,接近原生 解释执行,较慢 V8 优化,中等 解释执行,较慢 进程开销大
NuGet 生态 ✅ 450K+ 企业级库 PyPI 丰富 npm 庞大 模块有限 工具分散
跨平台 ✅ 真正统一 ✅ 良好 ✅ 良好 ⚠️ 依赖 PS Core ❌ Unix 限定
IDE 支持 ✅ VS Code 完整 ✅ 良好 ✅ 良好 ✅ 良好 ⚠️ 有限
原生系统集成 ✅ P/Invoke 完整 ⚠️ 需扩展 ⚠️ 需扩展 ✅ 深度集成 ✅ 深度集成
部署 ⚠️ 通常不预装但部署灵活 ✅ 通常已预装 ✅ 通常已预装 ✅ Windows 内置 ✅ Unix 内置
启动速度 ⚠️ 首次编译较慢 ✅ 快速 ✅ 快速 ✅ 快速 ✅ 极速

核心优势总结:

  1. 企业级生态:访问完整的 .NET 运行时和 NuGet 库,这是其他脚本语言难以比拟的
  2. 性能与安全的平衡:编译时类型检查 + JIT/AOT 优化,既保证安全又不失性能
  3. 渐进式复杂度:从 10 行脚本到 10 万行系统,同一套语言和工具链
  4. 现代化语言特性async/await、模式匹配、LINQ、源代码生成器等高级特性在脚本中完全可用
  5. 真正的跨平台:Windows、Linux、macOS 行为完全一致,无需适配
  6. “可进可退”的交付能力:既可以像脚本一样轻便传输源码,也可以像 Go/Rust 一样编译成无依赖的独立应用。

劣势主要在于:

  1. 首次运行有编译延迟
  2. 语言本身相对冗长
  3. 运行源码 (.cs) 需要安装 .NET 10 SDK(体积较大,200+ MB),但也可以:
  • 运行编译后的程序 (.dll),只需安装 .NET Runtime(体积较小,10+ MB)
  • 运行独立发布程序 (.exe) , 零依赖(Self-contained 或 AOT)

不仅仅是脚本——三种分发模式

与其他脚本语言不同,基于文件的 C# 程序拥有 .NET 完整的构建管道支持,这意味着你可以根据场景选择三种截然不同的分发方式:

  1. 源码分发

    • 方式:直接发送 .cs 文件。
    • 适用:团队内部工具、CI/CD 脚本、开发者之间的分享。
    • 特点:极轻量(几 KB),但在目标机器上需要安装 .NET SDK。
  2. 自包含发布

    • 方式dotnet publish script.cs --self-contained true
    • 适用:分发给非开发人员的工具。
    • 特点:无需目标机器安装 .NET Runtime/SDK。编译器会将运行时的一小部分(经过裁剪)和你的代码打包在一起。虽然体积较大(通常 20MB+),但确保了“解压即用”。
  3. 原生 AOT 编译

    • 方式dotnet publish script.cs -p:PublishAot=true
    • 适用:高性能命令行工具、容器化微服务、受限环境。
    • 特点:彻底脱离 .NET 运行时。直接编译为机器码,启动速度极快(毫秒级),内存占用极低,且难以被反编译。这是 Python 或 Node.js 难以企及的领域。

工具链与开发体验

VS Code 完整支持

作为目前最佳开发环境:

  • 安装 C# 和 C# Dev Kit 扩展
  • 设置 Dotnet > Projects: Enable File Based Programs 启用预览功能
  • 支持断点调试、IntelliSense、代码重构

命令行工具集

dotnet build script.cs      # 仅构建不运行
dotnet clean script.cs      # 清理构建缓存
dotnet restore script.cs    # 转换并生成 csproj 项目文件
dotnet publish script.cs    # 发布为独立可执行文件(.NET 10+ 支持)

配置文件支持

单文件程序支持配套 JSON 配置文件,实现更灵活的运行时管理:

my-web-app.cs
my-web-app.run.json      // 运行时配置(端口、环境变量等)
my-web-app.settings.json // 应用设置

对于 Web 项目,甚至可以携带 Blazor 组件,实现完整的单文件 SPA 应用。

当前限制

  1. .NET 10 仍不支持单文件程序直接引用另一个单文件程序(需转换为 csproj)。
  2. 指令必须出现在文件顶部,任何代码之前。
  3. 在项目编译中遇到这些指令会生成警告(它们专属于 file-based 模式)。、
  4. 最好保持单文件在 500 行以内,超出则考虑迁移到项目,如果是用AI生成的则随意。

未来展望

从 .NET 10 到 .NET 11 的路线图显示,这项技术正在快速演进:

  1. 单文件互引用:预告在 .NET 11 中实现,届时可以构建更复杂的单文件应用套件
  2. AI 生成友好:简单的文件结构使其成为 AI 代码生成的理想目标,我已在项目中验证 AI 可完全自动化生成此类应用
  3. 工具链完善:Visual Studio 最终将获得原生支持,Visual Studio Code 的体验将持续优化

结语

基于文件的 C# 程序不是简单的语法糖,而是微软对开发者痛点的深刻回应。它保留了 C# 的所有优势——类型安全、卓越性能、庞大生态——同时赋予了脚本语言的便捷性。从教学原型到生产工具,从 Web 微服务到系统自动化,这项技术正在重塑我们使用 C# 的方式。

当你下次需要编写一个小工具时,不妨试试 dotnet run script.cs,体验编译型语言与脚本便捷性的完美融合,这很可能是 C# 14 带来的最具影响力的革新。

Divider Line
标签: 砖工技术
作者: 宁嘉
日期:2025年12月16日

评论