惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
量子位
aimingoo的专栏
aimingoo的专栏
V
V2EX
Vercel News
Vercel News
B
Blog
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
TaoSecurity Blog
TaoSecurity Blog
N
News and Events Feed by Topic
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
S
Secure Thoughts
U
Unit 42
博客园 - 叶小钗
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
News | PayPal Newsroom
Help Net Security
Help Net Security
S
Security Affairs
Microsoft Security Blog
Microsoft Security Blog
W
WeLiveSecurity
博客园 - Franky
Forbes - Security
Forbes - Security
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Schneier on Security
Schneier on Security
I
InfoQ
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
A
About on SuperTechFans
Webroot Blog
Webroot Blog
AWS News Blog
AWS News Blog
Last Week in AI
Last Week in AI
Security Archives - TechRepublic
Security Archives - TechRepublic
C
CERT Recently Published Vulnerability Notes
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
Recent Commits to openclaw:main
Recent Commits to openclaw:main
J
Java Code Geeks

博客园 - 张善友

本体:AI落地的"企业翻译官" C# MCP SDK 2.0 即将发布:去会话化、去握手、去运维噩梦 数字员工的成本账:OpenClaw.NET 如何用工程化实现"成功任务的单位经济学"(下) AI 成本战的隐性成本与降本五层:从"成功率悖论"到"系统复杂度"(中) 从 Token 价格战到成功任务单位经济学:AI 成本战的真正主线(上) MCP + A2A 融合:协议层已就绪,信任层才是硬仗 22年微软MVP连任:一个.NET技术人的社区长跑 OpenClaw.NET 本体工程实践(一):数字员工的「语义大脑」不是数据库 当工厂里坐满了"数字员工":AI原生时代,NPI到量产正在被重写 当 AI 对话里直接弹出业务界面:MCP Apps 正在改写 SaaS 的集成逻辑 C# vs Go:Agentic 时代的语言分层 G#:当 Go、Kotlin 与 Swift 的美学遇见 .NET 运行时 从 Bun 的 Rust 重写,看 C# 如何重建 AI 基础设施层 从Kaplan到Test-Time Compute:Scaling Law的真实演变与中文媒体的叙事偏差 AI 基础设施的"去 Python 化":Rust 与 C# 的两条替代路径 你的 AI Agent 会在服务器上"修仙"——OpenClaw.NET 长持久会话技术解读 C# GeneratedRegex:面向对象语言的"底层性能突围 当 AI 不再只是"说话":OpenClaw.NET 率先原生支持 MCP Apps Token IO 架构的设计游戏:大模型产品形态四年演进的本质 将 Rust 绑定到 .NET 10:Oxigraph 的 FFI 桥接实践 Claude Code Dynamic Workflows vs OpenClaw.NET MetaSKILL C# ?? 链式回退:编写优雅的多级兜底逻辑 MetaSKILL 与 SKILL:多视角深度综述 Microsoft Agent Framework 1.0 正式接棒,.NET AI 进入 Agent-Native 时代 从 OpenClaw.NET 的 /loop 实现,看 Loop Engineering 如何从概念走向工程实践 OpenClaw.NET 祭出 TokenJuice:Agent 时代的"Token 瘦身引擎",让 LLM 上下文不再膨胀 OpenClaw.NET 重大更新:Goal 机制登场,让 AI Agent 不再"半途而废" OpenClaw.NET MetaSKILLs 系统深度解析:AI Agent 正在学会「自己给自己写技能」 OpenClaw.NET 上线 MetaSkills :软件工程第一性原理的工业级实践 当 AgentGateway 遇上 OpenClaw.NET:企业级智能体基础设施的深度协同实战 C# 内存安全性的重大演进:重新定义 unsafe 关键字 Qt Bridges for C# 深度技术解析 OpenClaw.NET 兼容性目录指南(Compatibility Catalog) .NET 10 桌面 UI 框架的范式演进:Jalium.UI 与 MewUI 架构深度对比 架构融合:Activity Host 作为确定性编排与认知智能代理的桥梁 MewUI 项目:面向 NativeAOT 的超轻量级.NET GUI 架构、底层图形管线与性能演进 人工智能原生时代的全栈工程范式转移:DeepSeek 人才战略与下一代 Agent 基础设施深度分析 OpenClaw.NET 外部 CLI 预设系统:从零编写第三方 CLI 集成指南 曝华为"白嫖"开源团队技术方案事件——网友评论总结 NuGet下载量数据分析与.NET生态全景观察:从数据洞察技术演进 .NET 11 Preview 4 正式发布:Runtime-Async 全面启用、Process API 大幅扩展 OpenClaw.NET:给智能以形态 OpenClaw.NET 外部 CLI 连接器 (External CLI Connectors) 详细技术总结 OpenHarmony.Avalonia 归档事件对中国自主软件生态的影响--信任的坍塌与生态的异化 Memgraph 与 Neo4j 图数据库对比及 .NET 生态适配分析 .NET生态系统中的A2A(Agent-to-Agent)协议支持与跨平台多智能体协同 OpenClaw.NET .NET 原生插件开发完全指南:以 Mempalace 插件为范例 为 openclaw.net 集成 ElBruno.MempalaceNet 记忆系统 Graphify-DotNet:AI 驱动的 .NET 代码知识图谱构建工具 SonnetDB:.NET 生态下的高性能嵌入式时序数据库 C# 原生编码智能体运行时 SharpClawCode SharpIDE: 基于 .NET 与 Godot 引擎的跨平台开源 IDE SharpDbg 与 netcoredbg 深度对比分析 .NET 调试器 netcoredbg 跨平台及其 LoongArch 架构支持进展 .NET生态下Native AOT兼容的Cron任务调度框架 Avalonia UI 12.0.0 正式发布:架构演进和性能飞跃 - 张善友 DotNetPy:现代.NET 与 Python 互操作 实战指南 微软发布的《生成式人工智能初学者.NET 10第二版》课程 Avalonia UI 12.0.0-RC1正式发布 自动导引车(AGV)与自主移动机器人(AMR)控制系统的 C# 开源封装库 AgentEval:面向 .NET 生态的企业级 AI 智能体评估框架 .NET 10 打造 OpenClaw Windows Node Microsoft Agent Framework:基于 DelegatingAIAgent 与 ChatClientAgent 的核心架构和协同范式 基于 Kubernetes 与多语言 SDK 的 OpenSandbox AI 代理沙箱编排 MCP C# SDK v1.0 正式发布 .NET 11 Preview 2 架构演进、技术深度解析 基于NativeAOT的 OpenClaw.NET 深度刨析 BMAD方法 v6 与 GitHub Copilot 在应用开发中的协同 C# 驱动的开源无人机机载飞控算法 《上海市卫生健康”信息技术应用创新”白皮书》C#/.NET “A组件”认定事件始末与最终结果 .NET 11 预览版 1 中的新兴架构演进:RISC-V 与 LoongArch 支持的深度技术解析与生态展望 .NET 11 预览版1:CoreCLR 在 WebAssembly 上的全面集成与性能突破 .NET 11与智能体人工智能的范式转移:架构演进、开发者生态与安全解析 Lucia 智能家居自治系统:基于多智能体编排与边缘计算融合 Model Context Protocol (MCP) C# SDK v0.9.0-preview.1 发布
.NET 10 File-Based Apps:一个 .cs 文件搞定一切,C# 终于也能像 Python 一样写脚本了!
张善友 · 2026-07-08 · via 博客园 - 张善友

引言:告别 .csproj,C# 也能"单文件即运行"

还记得用 Python 写脚本时的那种爽快感吗?一个 .py 文件,直接 python hello.py 就能跑。而 C# 开发者呢?哪怕只是想写个"Hello World",也得先 dotnet new console 生成一堆项目文件,然后才能编译运行。

这种"仪式感",在 .NET 10 中终于成为历史。

.NET 10 引入了一个重磅新特性——File-Based Apps(文件级应用)。它允许你仅用一个 .cs 文件,无需任何 .csproj 项目文件,就能直接编译、运行、甚至发布为独立可执行文件。C# 从此真正具备了脚本语言的开发体验,同时保留了编译型语言的性能优势。


一、什么是 File-Based Apps?

File-Based Apps 是 .NET 10 SDK 引入的一项创新功能,允许开发者从单个 C# 源文件构建、运行和发布 .NET 应用程序,无需创建传统的项目文件(.csproj)。

.NET SDK 会自动根据源文件顶部的 #: 指令生成必要的项目配置,为脚本、工具和小型应用提供了一种轻量级的替代方案。

核心优势

特性 说明
零配置 无需 .csproj 文件,一个 .cs 文件即可运行
自包含 配置内嵌在源文件中,文件即项目
Native AOT 默认启用 发布时自动生成本地 Ahead-of-Time 编译的可执行文件
自动打包为 .NET 工具 支持 dotnet pack 直接打包为全局工具
平滑升级 可随时通过 dotnet project convert 转换为完整项目

二、环境准备

要使用 File-Based Apps,你需要:

  • .NET 10 SDK 或更高版本
  • 任意文本编辑器(VS Code、Cursor、记事本均可)
  • C# 扩展(推荐,用于 IntelliSense 支持)

验证 SDK 版本:

dotnet --version
# 输出应为 10.0 或更高

三、快速上手:5 分钟写出第一个 File-Based App

3.1 最简单的 Hello World

创建一个文件 hello.cs

Console.WriteLine("Hello, File-Based App!");

直接运行:

dotnet run hello.cs

或者使用更简洁的语法:

dotnet hello.cs

没错,就这么简单!没有 dotnet new,没有 .csproj,一个文件直接跑。


3.2 引用 NuGet 包:#:package 指令

File-Based Apps 使用 #: 前缀的指令来配置构建。最常用的就是 #:package,用于引用 NuGet 包。

创建一个 sqlite-demo.cs

#:package Microsoft.Data.SQLite@8.0.0

using Microsoft.Data.Sqlite;

var connectionString = "Data Source=:memory:";
using var connection = new SqliteConnection(connectionString);
connection.Open();

var command = connection.CreateCommand();
command.CommandText = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);" +
                      "INSERT INTO users (name) VALUES ('山友');" +
                      "SELECT * FROM users;";

using var reader = command.ExecuteReader();
while (reader.Read())
{
    Console.WriteLine($"ID: {reader.GetInt32(0)}, Name: {reader.GetString(1)}");
}

运行:

dotnet run sqlite-demo.cs

输出:

ID: 1, Name: 山友

版本控制技巧

  • #:package Newtonsoft.Json — 省略版本号(需配合 Central Package Management)
  • #:package Serilog@3.1.1 — 指定精确版本
  • #:package Spectre.Console@* — 使用最新版本

3.3 指定 SDK:#:sdk 指令

默认使用 Microsoft.NET.Sdk,但你可以轻松切换为 Web SDK 或 Aspire SDK:

#:sdk Microsoft.NET.Sdk.Web
#:package Swashbuckle.AspNetCore

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

app.MapGet("/", () => "Hello from File-Based Web App!");
app.MapGet("/api/health", () => new { status = "ok", timestamp = DateTime.UtcNow });

app.Run();

运行:

dotnet run webapi.cs

使用 Microsoft.NET.Sdk.Web 时,会自动包含同目录下的 *.json 配置文件(如 appsettings.json)。


3.4 设置 MSBuild 属性:#:property 指令

#:property TargetFramework=net10.0
#:property PublishAot=false
#:property LogLevel=$([MSBuild]::ValueOrDefault('$(LOG_LEVEL)', 'Information'))

Console.WriteLine($"Current Log Level: {Environment.GetEnvironmentVariable("LOG_LEVEL") ?? "Information"}");

#:property 支持完整的 MSBuild 属性表达式,包括环境变量读取、条件表达式等。


3.5 引用其他项目:#:project 指令

#:project ../SharedLibrary/SharedLibrary.csproj

using SharedLibrary;

Console.WriteLine(Helper.GetMessage());

四、完整的 CLI 命令支持

File-Based Apps 并非"玩具功能",它拥有完整的 CLI 支持:

运行应用

# 标准方式
dotnet run --file app.cs

# 简写(推荐)
dotnet run app.cs

# 更简写(当目录无 .csproj 时)
dotnet app.cs

# 传递参数
dotnet run app.cs -- arg1 arg2

# 从标准输入管道执行
echo 'Console.WriteLine("hello from stdin!");' | dotnet run -

构建与清理

# 编译
dotnet build app.cs

# 清理构建产物
dotnet clean app.cs

# 清理所有 file-based apps 缓存
dotnet clean file-based-apps

发布与打包

# 发布(默认启用 Native AOT,生成独立可执行文件)
dotnet publish app.cs

# 打包为 .NET 全局工具
dotnet pack app.cs

# 转换为传统项目(平滑升级路径)
dotnet project convert app.cs

依赖恢复

# 显式恢复 NuGet 包
dotnet restore app.cs

# 构建时自动恢复(默认行为)
dotnet build app.cs

五、Native AOT:默认开启的高性能发布

File-Based Apps 的一个杀手锏特性是默认启用 Native AOT 发布。这意味着:

  • 更快的启动速度 — 无需 JIT 编译预热
  • 更小的内存占用 — 无运行时依赖
  • 独立可执行文件 — 单文件分发,无需 .NET Runtime

如果你不需要 AOT(例如依赖反射较多的场景),可以关闭:

#:property PublishAot=false

六、用户机密(User Secrets)

File-Based Apps 支持用户机密管理,基于文件路径的哈希生成稳定的 Secrets ID:

# 设置机密
dotnet user-secrets set "ApiKey" "your-secret-value" --file app.cs

# 查看机密
dotnet user-secrets list --file app.cs

七、Unix 系统上的 Shebang 支持

在 Linux/macOS 上,你可以让 .cs 文件像 Shell 脚本一样直接执行:

#!/usr/bin/env dotnet
#:package Spectre.Console

using Spectre.Console;

AnsiConsole.MarkupLine("[green]Hello, World![/]");

赋予执行权限并运行:

chmod +x app.cs
./app.cs

⚠️ 注意:使用 Shebang 时,文件必须使用 LF 换行符,不能包含 BOM。


八、Launch Profile 配置

File-Based Apps 支持启动配置,使用 [应用名].run.json 文件:

// app.run.json
{
  "profiles": {
    "http": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

运行指定 Profile:

dotnet run app.cs --launch-profile https

九、目录组织最佳实践

File-Based Apps 会继承父目录的 Directory.Build.propsDirectory.Packages.props 等隐式构建文件。为了避免冲突:

❌ 不推荐

📁 MyProject/
├── MyProject.csproj
├── Program.cs
└──📁 scripts/
    └── utility.cs  // 会受到 MyProject.csproj 的隐式文件影响

✅ 推荐

📁 MyProject/
├── MyProject.csproj
└── Program.cs
📁 scripts/
└── utility.cs  // 独立目录,避免干扰

十、实战场景:File-Based Apps 能做什么?

场景 1:快速原型验证

#:package Newtonsoft.Json

using Newtonsoft.Json;

var data = new { Name = "File-Based App", Version = "1.0", Features = new[] { "Fast", "Simple", "Powerful" } };
Console.WriteLine(JsonConvert.SerializeObject(data, Formatting.Indented));

场景 2:CLI 工具脚本

#!/usr/bin/env dotnet
#:package Spectre.Console
#:package System.CommandLine

using Spectre.Console;
using System.CommandLine;

// 构建一个功能完整的 CLI 工具
var rootCommand = new RootCommand("文件批量重命名工具");
var patternOption = new Option<string>("--pattern", "匹配模式");
rootCommand.AddOption(patternOption);

rootCommand.SetHandler((string pattern) =>
{
    AnsiConsole.MarkupLine($"[blue]正在处理匹配模式: {pattern}[/]");
    // 业务逻辑...
}, patternOption);

await rootCommand.InvokeAsync(args);

场景 3:数据迁移/ETL 脚本

#:package Dapper
#:package Microsoft.Data.SqlClient
#:package CsvHelper

using Dapper;
using Microsoft.Data.SqlClient;
using CsvHelper;
using System.Globalization;

// 从数据库读取,写入 CSV — 一个文件搞定数据迁移

场景 4:定时任务/自动化脚本

#:package Quartz

// 使用 Quartz 构建定时任务,部署为单文件后台服务

十一、File-Based Apps vs 传统 .csproj 项目

对比维度 File-Based Apps 传统 .csproj 项目
项目文件 ❌ 不需要 ✅ 需要
适合场景 脚本、工具、原型、小型应用 中大型应用、团队协作
启动速度 ⚡ 更快(AOT 默认) 🔄 标准 JIT
依赖管理 #: 指令内嵌 PackageReference
测试支持 ❌ 不支持 dotnet test ✅ 完整支持
团队规模 个人/小团队 任意规模
升级路径 dotnet project convert 本身就是完整项目

关键洞察:File-Based Apps 不是替代传统项目,而是填补空白——在那些"为了写个脚本还得建个项目"的场景下,它提供了恰到好处的轻量方案。


十二、从 File-Based App 到完整项目

当你的脚本逐渐复杂,需要单元测试、CI/CD 或多项目结构时,File-Based Apps 提供了平滑的升级路径:

dotnet project convert app.cs

执行后,SDK 会:

  1. 复制 .cs 文件到以应用名命名的目录
  2. 根据 #: 指令生成等效的 .csproj 文件
  3. 保留原始文件不变

十三、写在最后

.NET 10 的 File-Based Apps 是一个看似小巧、实则意义深远的特性。它标志着 .NET 平台在开发体验上的一次重要进化:

  • 对初学者:降低了 C# 的入门门槛,一个文件就能开始编程
  • 对脚本开发者:C# 终于可以像 Python 一样写脚本,同时享受编译型语言的性能
  • 对运维/DevOps:单文件可执行,部署极简,Native AOT 带来极致启动速度
  • 对原型开发:快速验证想法,需要时再平滑升级为完整项目

C# 不再是"重型企业级开发"的专属标签,它也能轻盈、敏捷、即刻运行。


参考资源