大数跨境
0
0

.NET 10  里更简单的 C#

.NET 10  里更简单的 C# amazingdotnet
2025-12-02
0
导读:.NET 10 更简单的 C#

 

.NET 10  里更简单的 C# dotnet app.cs


Intro

什么是文件程序呢,文件程序就是基于 C# 源文件的程序,传统的 C# 我们需要项目文件才能运行,而文件程序只需要一个源文件就能执行,文件程序主要的特点就是不需要项目文件,又被称为 run file,或者 file-based programs 或者 file-based apps。

它极大地简化了 C#,对于 C# 初学者来说非常友好,能够降低初学者学习的门槛,只需要将关注点放在 C# 语言上而无需关注项目、项目文件、 等一系列概念,它还特别适合做一些原型验证(PoC)、教学、脚本和自动化等,同时当单文件变得维护性差变得复杂的时候我们也可以一键转换成项目,转变成通过项目来管理,功能还会保持不变。

这里是一个 hello world 的示例,这个 hello.cs 文件里只有一行代码 Console.WriteLine("Hello World");  输出一个 Hello World,我们直接执行 dotnet hello.cs 就可以运行


what is file app

C# 简化演进过程

这一特性主要就是为了简化 C#,它背后其实是很多版本发展而来的,是 C# 和 .NET 长期以来不断简化的结果,不仅是 C# 语言特性的简化也是项目文件的简化。

在最初 .NET Framework C# 1.0 时代,我们写 C# 一定要有 Main 方法和复杂的项目文件,每个文件都会出现在项目文件,到 .NET Core 出现之后,项目文件大大的简化了,之前每个项目都需要显式的包含在项目里,新的项目文件默认会包含大大简化了项目文件,

到 .NET 6 我们支持 top-level statements 顶级语句我们现在已经可以不用写 Main 方法了,入口更加简洁,global using 和隐式引用使得我们的程序更加的简单,常用的命令空间引用自动引用,再到现在的 .NET 10,SDK 进一步支持直接将单个文件作为完整程序写完就可以 dotnet 执行了


C# Simplicity

How

你可能会好奇:既然没有项目文件,那它是怎么运行的?关键在于 SDK 会在运行时动态构建一个内存中的虚拟项目(in-memory virtual project)。
 虽然你看不到 .csproj,但编译器依然在完整运作。它会进行引用解析,nuget 包还原,编译检查等,仍然能够引用 NuGet 包或者其他项目。


How it works

从这里的 dotnet build 的 log 可以看得出来,这里实际还是有项目文件的概念

默认启用了 terminal logger 不会显示这么多 log,我们这里的示例是通过环境变量禁用了默认的 terminal logger   export MSBUILDTERMINALLOGGER=off

让他输出所有的 log,这里就可以清晰地看到 build 的过程中有项目文件了,但实际上这个目录下只有一个 hello.cs 文件没有项目文件,这个文件是一个只存在于内存里的虚拟项目文件,最后 build 构建出来的也是一个 dll 和编译项目是完全一样的


disable terminal logger

How to use

shebang

接下来介绍一下如何使用,首先我们稍微改下之前的示例,我们在第一行加了一行特殊的代码 #!/usr/bin/env dotnet 这行代码主要在 Linux/Mac 上可用,用来指定这个文件使用 dotnet 来执行,接着我们使用 chmod +x 来指定这个文件是可以执行的,这样我们就可以直接执行 hello.cs 了,和使用 dotnet hello.cs 效果是一样的


shebang

Reference


References

文件程序支持外部引用,可以引用一个本地项目,可以通过 #:project 来指定项目所在目录或者项目路径,也可以通过 #:package 来指定一个 nuget 包引用,这里是一个简单的示例,这里第一个例子就是引用了一个本地项目,然后第二个是引用了一个 nuget 包,除了 nuget 包引用它还指定了一个 sdk 使用 web sdk,这样会自动引用 web 框架,自动添加 AspNetCore 框架引用,这里我们还指定了两个 property, 一个是关闭了包版本的统一管理 ()ManagePackageVersionsCentrally=false),因为上级目录启用了全局包版本管理,这里想单独指定,所以指定 property 关掉了,还有一个 PublishAot,在文件程序里 Aot 默认是打开的,有些用法如果不是 aot 安全的会有 warning,这里禁用掉了(PublishAot=false),这和在项目文件里指定一个 Property 是一样的(<PublishAot>false</PublishAot>)

这里是另外一个 web api 的示例,这里是 .NET 10 里的一个新特性,返回 Server Sent Event 的一个示例,这里只指定了 web sdk 没有引用额外的 nuget 包


web sample 2

Build

文件程序会自动应用文件路径上的隐式 build file,常见的有 Directory.Build.props/targets 以及前面提到的统一管理 nuget 包版本的 Directory.Packages.props

除了直接执行 dotnet cs 文件之外, 我们还可以 dotnet restore/dotnet build

注意的话前面我们输出的 path 是一个 runfile 的临时目录,这里我们的例子定义了一个 Directory.Build.props 文件里面定义了 ArtifactsPath并设置为了当前目录下的 artifacts 目录,我们再 build 及会看到它的 path 是当前目录下新建了一个 artifacts 目录


dotnet build app.cs

另外注意的话会看到第一次 build 的时间比较长,后面再次 build 的时候会比较快,这是因为会有缓存,后面再 build 就可以重用缓存

除了 build 我们还可以使用 dotnet clean/dotnet publish


`dotnet clean/publish/format`

使用 dotnet clean 可以清除缓存清除上次 build 的输出文件,前面我们说了 dotnet publish 默认会 aot 发布,所以这里我们可以看到发布之后直接就是一个可以执行的 exe 没有 dll,如果是普通的框架依赖发布会包含有 dll

我们可以直接执行这个 exe 可以正常看到输出结果和 dotnet hello-csharp14.cs 输出结果一致
目前 dotnet format 还不支持对单个 cs 文件使用,所以 dotnet format 单个文件现在会报错,Github 上已经有 issue,在 .NET 11 可能可以用上

Convert

当你的单文件变得复杂或者希望在项目里使用的时候,可以使用 dotnet project convert 命令来将单文件转换成项目,官方叫成长为项目 growup

这里是将前面的 hello.cs 转换成项目的一个示例,变成项目之后和原来的单文件的功能完全一致,这里可以看到转换前后的输出是完全一样的


dotnet project convert

Config

文件程序里有两个特殊的配置文件,分别是文件同名的 run.json 和 settings.json

run.json 对应了 ASP.NET Core 里的 launchSettings.json,我们可以指定环境变量,应用的 url 等,这里是一个 run.json 的示例,这里指定了 url 是 file-api.dev.localhost 从下面控制台的输出可以看到这个 run.json 有被读取并应用到,这里的 file-api.dev.localhost 地址也是 .NET 10 的一个新特性,现在可以给 localhost 加子级域名来更好的区分服务


run.json


接着我们来看下 settings.json ,它则类似于 appsettings.json,我们可以指定一个同名的 api.settings.json ,在使用 WebApplication.Create/WebApplication.CreateBuilder 的时候会自动加载(感觉使用 WebApplication.CreateSlimBuilder 也应该要加载,但是目前并没有加载)

这里我引用了自己实现的一个 nuget 里的一个中间件,可以查看当前配置 MapConfigInspector,下面的截图可以看出我们的 API 读到了我们 api.settings.json 中的配置


setting.json

settings.json 就像 appsettings.json 一样,也是支持环境的,比如我们再加一个 api.settings.Development.json 并修改配置让他们不一样

接着再跑一下看一下可以看到我们的 Development.json 配置也被读取了,并且实际生效的配置是来自 api.settings.Development.json 的


settings.Development.json

HelloAvalonia Sample

借助文件程序我们可以将很多框架应用做一个最简化来方便上手,这对于理解框架运行最简单的应用需要有哪些模块会比较有帮助

这里是一个 Avalonia 的单文件 Hello World 应用,前面我们也有 api 的应用,也可以实现一个 WPF 应用等等


file-based hello avalonia

Multiple Files Sample

前面我们展示的文件程序都是单文件的,那么可以支持多文件吗?目前官方还不支持官方支持要等 .NET 11
但是我们借助自动引用 build file 自己实现一个简单的多文件的支持,这里是自己实现的一个多文件的示例


multiple-files support
左边是一个帮助类,中间的这个是单文件入口,依赖于左边的帮助类中定义的方法,右边是一个 build targets 文件,将 Imports 这个属性里的文件在 Build 的时候参与到编译中,下面的执行输出结果说明我们的方法是可以工作的

CI Sample

除此之外,我还将它用在了 CI 上,这里是一个 CI 的构建脚本示例,会构建整个项目并执行测试用例,最后会打包 nuget 包,最后需要的话推送到 nuget.org,这个项目里是通过项目文件引用,还有别的项目里是通过 nuget 包的引用,基本是一样的,右边是 github actions 里的定义 CI 里直接使用 dotnet build.cs 来验证,之前还需要分平台 Windows 上使用 build.ps1 在 Linux 上使用 build.sh, 现在都用 dotnet build.cs 即可


CI-sample


IDE

目前文件程序在 VS 里还不支持,在 VS Code 里可以安装 C# 扩展支持,不过目前还是预览版本功能,所以需要手动启用,后面变成正式版功能就无需手动启用了,应该很快就可以了

在 C# 扩展的设置里搜索 file 就可以找到对应的 File-based Progarms 功能,打勾启用之后在编辑单文件 C# 的时候就会有智能提示了


enable vscode file-based program feature

并且现在 nuget 网站上现在也有针对文件程序的包引用格式了,现在多了一个 File-based Apps 的选项栏,切换过去之后可以直接拷贝 nuget 包引用代码


nuget.org file-based app reference

Next

文件程序未来会继续增强,包括正式的多文件支持,多目标框架支持目前只支持一个目标框架,以及前面提到的 dotnet format 支持、支持调试、更快的启动速度,以及与整个 dotnet 工具链更紧密的整合等等,希望它越来越好用吧


next

最后有一些参考链接和更多的学习资料,大家希望了解更多的话可以看一看


References

  • • https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md
  • • https://github.com/dotnet/roslyn/blob/main/docs/features/file-based-programs-vscode.md
  • • https://github.com/dotnet/sdk/pulls?q=is%3Apr+label%3AArea-run-file
  • • https://github.com/dotnet/sdk/issues?q=is%3Aissue+label%3AArea-run-file
  • • https://github.com/WeihanLi/SamplesInPractice/tree/main/net10sample/file-programs
  • • https://github.com/WeihanLi/SamplesInPractice/tree/main/AvaloniaSamples/file-scripts
  • • https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10/sdk?WT.mc_id=DT-MVP-5004222
  • • https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/
  • • https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/overview#file-based-programs
  • • https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/#building-and-running-c-programs
  • • https://github.com/DamianEdwards/runfile

 

【声明】内容源于网络
0
0
amazingdotnet
dotnet 开发知识库,了不起的 dotnet,dotnet 奇淫怪巧
内容 539
粉丝 0
amazingdotnet dotnet 开发知识库,了不起的 dotnet,dotnet 奇淫怪巧
总阅读240
粉丝0
内容539