在.NET 10中的基于文件的C#执行
[[academy-video-youtube({"vid": "2i0MJDHvJq0", "start_time": "0", "title": ".NET 10 中基于文件的 C# 执行", "creator": "Tim Corey", "length": "13m 36s"})]]
C# 始终需要一个项目文件才能运行代码。 即使是最简单的"Hello World"也需要一个Program.cs和一个构建步骤才能执行。 在 .NET 10 中,这发生了变化。 您现在可以编写一个.cs文件并直接运行,就像执行Python脚本或Node.js文件一样。
在他的视频"File-Based C# Execution in .NET 10"中,Tim Corey 全面演示了此功能的每个方面:运行独立文件、传递命令行参数、在代码中添加 NuGet 软件包、发布为本机可执行文件,以及在范围超出单文件格式时将文件转换为完整项目。 如果您之前使用控制台应用进行快速脚本和原型设计,这将显著改变工作流程。
运行一个 C# 文件
[0:40 - 1:48] Tim 在 VS Code 中以空文件夹开始。 无解决方案,无项目文件,无样板。 他创建了一个名为demo.cs的单文件,其中包含一行代码:
Console.WriteLine("Hello World");Console.WriteLine("Hello World");执行它:
dotnet run file demo.csdotnet run file demo.cs这就是完整的工作流程。 obj文件夹。 心智模型更接近脚本而不是传统的 C# 开发:编写文件,运行它,查看输出。
Tim 直接将其与 Python 和 JavaScript 进行比较,其中单文件执行一直是默认。 .NET 10 将 C# 带到同一领域,同时保持 C# 首先令人吸引的类型安全性和性能。
命令行参数和隐式 using
[1:48 - 3:26] Program.cs中一样。 Tim 修改文件以接受名称参数:
Console.WriteLine($"Hello {args[0]}");Console.WriteLine($"Hello {args[0]}");用一个参数运行它:
dotnet run file demo.cs Timdotnet run file demo.cs Tim这将打印"Hello Tim"。 Tim指出using System;语句的情况下也能工作,因为基于文件的执行默认包含隐式的using。 这是 C# 9 中引入的顶级语句的相同行为,现在扩展到独立文件中。
微软一直在遵循的更广泛模式是逐个版本地精简C#中的繁文缛节。全局using、顶级语句,现在还有独立的.cs文件,都是为了使C#在需要快速任务时可行的步骤,以前这些任务需要Python或bash脚本。
添加用户输入
[3:26 - 5:43] Tim 用交互式输入替代参数方法,以演示文件执行支持完整范围的控制台应用模式:
Console.Write("What is your name? ");
string name = Console.ReadLine();
Console.WriteLine($"Hello {name}");Console.Write("What is your name? ");
string name = Console.ReadLine();
Console.WriteLine($"Hello {name}");运行此命令后,会提示输入、读取响应并打印问候语。 标准 I/O 与完整项目完全相同。
Tim提到的一个限制:这种模式严格来说是单文件的。不能有两个.cs文件相互引用。 如果代码增长到需要多个文件,是时候转换为项目(视频后面部分将介绍)。
引入 NuGet 包
[5:43 - 7:49] 这是单文件方法在脚本中真正有用的地方。 您可以在#r指令直接引用NuGet包:
#r "nuget:Spectre.Console, 0.54.0"
using Spectre.Console;
Console.Write("What is your name? ");
string name = Console.ReadLine();
AnsiConsole.MarkupLine($"Hello [red]{name}[/]");#r "nuget:Spectre.Console, 0.54.0"
using Spectre.Console;
Console.Write("What is your name? ");
string name = Console.ReadLine();
AnsiConsole.MarkupLine($"Hello [red]{name}[/]");#r "nuget:..."语法告诉运行时在编译前下载并引用指定的包。 Tim 使用Spectre.Console着色输出,将问候语文本变为红色。
没有.csproj需要编辑,没有恢复步骤。包引用存在于源码文件本身中。 对于需要 HTTP 客户端、JSON 序列化器或格式库的脚本,这消除了仅为引入一个依赖项而创建项目的开销。
发布到本机可执行文件
[7:49 - 8:59] 当您想要以独立二进制文件分发基于文件的脚本时,发布命令可以处理它:
dotnet publish file demo.csdotnet publish file demo.cs这会在artifacts文件夹中生成一个可执行文件。 编译的二进制包含运行所需的一切,不需要在目标机器上安装 .NET SDK。Tim 指出,基于文件的构建默认使用 Native AOT,这意味着输出是一个单一的,独立的二进制,启动时间快。
如果Native AOT导致与特定库的不兼容问题,您可以通过在文件顶部添加属性指令来禁用它(类似于#r用于包的方式)。 不过对于大多数脚本用例,AOT 是正确的默认值。
转换为完整项目
[8:59 - 10:45] 当脚本超出单文件格式时,转换命令是一个逃生舱:
dotnet project convert file demo.csdotnet project convert file demo.cs这会生成一个.csproj文件,其中包括NuGet包引用自#r指令,并将代码移至标准项目结构中。 从此之后,您可以添加多个文件,配置构建设置,并使用完整的 .NET 项目系统。
Tim 将此视为自然的进步:从单文件快速实验开始,当范围扩大时,将其提升为项目而无须重写任何内容。 <PackageReference>条目。
Native AOT 和平台说明
[10:45 - 12:42] 默认情况下,基于文件的执行使用 Native AOT 编译,产生尽可能快的启动时间。 Tim 指出,这对需要冷启动性能的 CLI 工具和脚本来说是理想的。 如果某个库不兼容 AOT,可以通过文件级属性禁用该功能。
在Linux和macOS上,您还可以在.cs文件顶部添加一个hashbang (dotnet run file前缀。 这使 C# 完全进入脚本领域,与 bash、Python 和 Ruby 并驾齐驱。
总结:C# 作为脚本语言
[12:42 - 13:05] Tim 强调最重要的影响是减少小任务的项目开销。 控制台应用程序一直是快速实验、自动化脚本和一次性工具的首选。 基于文件的执行消除了让这些感觉比实际更重的仪式,同时保留了使 C# 值得选择的所有优势(类型安全、性能、NuGet 生态系统),而不是脚本语言。
结论
[13:05 - 13:36] 简而言之:.NET 10的基于文件执行允许您运行一个带有dotnet project convert file转为完整项目,超越单文件格式时。 Native AOT 默认开启,Linux/macOS 用户可以使用 hashbang 支持进行 Shell 级执行。
对于您当前使用控制台应用进行原型或自动化的任何内容,这作为一种更轻量的替代方式值得尝试。
示例提示:如果您发现自己创建控制台应用只是为了测试 NuGet 包或调试 API 调用,请尝试基于文件的执行。 创建一个dotnet run file运行。 完成后,删除文件。无需进行项目清理。

