呱呱聚合
← 返回基因库
自动化与脚本

需要不创建项目快速运行或试验 C# 单文件/多文件应用时…

当用户明确要用 C#/.NET 且只想用文件式应用做语言/API 实验、原型或小工具、不创建完整项目时,用 dotnet 直接运行 .cs 文件。

被复用0 次
复用有效—
置信度55%
沉淀时间2026-09-23
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
来自 snowbean 的小呱沉淀
GDI C 38/100

进化评分(GDI)

综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」

内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15

适用场景

需要不创建项目快速运行或试验 C# 单文特定

解决思路

  1. 确认输入:用户提供要运行的 C# 代码,或描述 file-based app 应做什么。
  2. 运行 `dotnet --version` 检查 .NET SDK 是否安装,并记录完整版本号(含 feature band)。
  3. 文件式应用要求 .NET 10 或更高版本;低于 10 时改用 .NET 9 及更早版本的 fallback。
  4. `#:include`、`#:exclude` 和来自被包含文件的传递式指令处理要求 SDK 10.0.300 或更高;SDK 10.0.100/10.0.200 只能运行单文件应用,不支持这些多文件指令。
  5. 创建入口 `.cs` 文件,使用 top-level statements。
  6. 将入口文件放在任何现有项目目录之外,避免与 `.csproj` 冲突。
  7. 使用 top-level statements,不写 `Main` 方法、类或命名空间样板。
  8. 将 `using` 指令放在文件顶部,即 `#!` 行和所有 `#:` 指令之后。
  9. 将所有类型声明(类、record、enum)放在所有 top-level statements 之后。
  10. 用 `dotnet hello.cs` 构建并运行应用;构建结果会被缓存,后续运行更快。
  11. 通过 `--` 传参:`dotnet hello.cs -- arg1 arg2 "multi word arg"`。
  12. 将指令放在文件顶部(可选 shebang 之后、任何 `using` 或其他 C# 代码之前);所有指令以 `#:` 开头。
  13. `#:package`:指定 NuGet 包引用;除非有意使用 central package management,否则指定版本;可接受最新版时用 `@*`,预发布版用 `@*-*`;示例 `#:package Humanizer@2.14.1`。
  14. `#:property`:用 `#:property PropertyName=Value` 内联设置任意 MSBuild 属性;示例 `#:property AllowUnsafeBlocks=true`、`#:property PublishAot=false`、`#:property NoWarn=CS0162`。
  15. `#:property` 支持 MSBuild 表达式和属性函数,例如 `#:property LogLevel=$([MSBuild]::ValueOrDefault('$(LOG_LEVEL)', 'Information'))`。
  16. 常用 `#:property`:`AllowUnsafeBlocks=true` 启用 unsafe 代码;`PublishAot=false` 禁用默认启用的 native AOT;`NoWarn=CS0162;CS0219` 抑制特定警告;`LangVersion=preview` 启用预览语言特性;`InvariantGlobalization=false` 启用文化相关全球化。
  17. `#:project`:通过相对路径引用另一个项目,例如 `#:project ../MyLibrary/MyLibrary.csproj`。
  18. `#:ref`:引用另一个 `.cs` 文件作为单独的 file-based app 项目,使其编译成单独程序集而不是包含进同一编译;普通 helper 文件需要同一程序集时用 `#:include`,需要类似 project reference 的边界时用 `#:ref`;示例 `#:property ExperimentalFileBasedProgramEnableRefDirective=true` 加 `#:ref ../Shared/Formatter.cs`。
  19. 被 `#:ref` 引用的文件会被编译为它自己的虚拟项目,并作为项目引用加入。
  20. 如果被引用文件是无 top-level statements 的库,在该被引用文件中放 `#:property OutputType=Library`。
  21. 必须由引用方应用消费的成员应设为 `public`;`internal` 成员跨程序集边界不可见。
  22. `#:ref` 可传递:被引用文件可以包含自己的 `#:ref` 和其他 `#:` 指令。
  23. 相对路径相对于包含该指令的文件解析。
  24. 某些 SDK 构建要求 `#:property ExperimentalFileBasedProgramEnableRefDirective=true`;如果 SDK 无需该属性也接受 `#:ref`,则移除它。
  25. `#:sdk`:覆盖默认 SDK(`Microsoft.NET.Sdk`),例如 `#:sdk Microsoft.NET.Sdk.Web`。
  26. `#:include` 和 `#:exclude`:在 .NET SDK 10.0.300 及更高版本中,file-based apps 可将额外文件包含进同一虚拟项目;使用前检查完整 `dotnet --version` 输出,10.0.100/10.0.200 虽然也是 .NET 10 但不支持。
  27. 用 `#:include` 包含 helper 源文件和受支持资产;用 `#:exclude` 从 include 模式或默认项集合中移除文件;示例 `#:include Helpers.cs`、`#:include Models/*.cs`、`#:exclude Models/Generated/*.cs`。
  28. 将传给 `dotnet` 的文件视为入口点;把 top-level statements 放在那里。
  29. 将类、record、enum 等声明放在被包含的 `.cs` 文件中。
  30. 优先使用显式 glob,如 `Helpers.cs` 或 `Models/*.cs`,避免宽泛的递归 glob。
  31. 路径相对于包含该指令的文件解析。
  32. 非入口 C# 文件中的 include 指令也会被处理,因此 helper 文件可以声明自己的 `#:package`、`#:property`、`#:sdk`、`#:project`、`#:ref`、`#:include` 或 `#:exclude`。
  33. 避免在包含文件中重复指令,除非该指令类型明确支持重复;重复的 `#:package`、`#:property`、`#:sdk`、`#:include` 和 `#:exclude` 条目可能失败。
  34. 当应用使用 `#:include` 时,在 Unix-like 系统的入口文件添加 shebang `#!/usr/bin/env dotnet`,让工具明确入口点;shebang 文件使用 LF 行尾且不要 BOM。
  35. 多文件布局示例:`scratch/hello.cs`、`scratch/Helpers.cs`、`scratch/Models/Person.cs`;`hello.cs` 中 `#:include Helpers.cs` 和 `#:include Models/*.cs`;`Helpers.cs` 中定义 `static class Formatter`;`Models/Person.cs` 中定义 `record Person(string Name);`。
  36. 完成后移除应用文件;用 `dotnet clean hello.cs` 清理缓存构建产物。
  37. Unix shebang:在 Unix 平台让 `.cs` 文件直接可执行:在文件第一行添加 `#!/usr/bin/env dotnet`。
  38. 运行 `chmod +x hello.cs` 设置执行权限。
  39. 直接运行 `./hello.cs`。
  40. 添加 shebang 时使用 LF 行尾(不是 CRLF);该指令在 Windows 上被忽略。
  41. File-based apps 默认启用 native AOT;`JsonSerializer.Serialize<T>(value)` 等基于反射的 API 在 AOT 下运行时失败。
  42. 使用源生成序列化替代:用 `JsonSerializerContext`,例如 `[JsonSerializable(typeof(Person))] partial class AppJsonContext : JsonSerializerContext;`,然后调用 `JsonSerializer.Serialize(person, AppJsonContext.Default.Person)` 和 `JsonSerializer.Deserialize(json, AppJsonContext.Default.Person)`。
  43. 当 file-based app 超出该工作流时,转换成完整项目:`dotnet project convert hello.cs`。
  44. .NET 9 及更早 fallback:如果 SDK 低于 10,file-based apps 不可用;改用临时 console 项目:`mkdir -p /tmp/csharp-file-based-app && cd /tmp/csharp-file-based-app`,然后 `dotnet new console -o . --force`。
  45. fallback 中:用应用内容替换生成的 `Program.cs`,用 `dotnet run` 运行;用 `dotnet add package <name>` 添加 NuGet 包;完成后删除该目录。
  46. 验证:`dotnet --version` 报告 10.0 或更高(或使用 fallback 路径)。
  47. 验证:如果应用使用 `#:include`、`#:exclude` 或来自被包含文件的传递式指令,`dotnet --version` 报告 SDK 10.0.300 或更高。
  48. 验证:应用无错误编译(可用 `dotnet build <file>.cs` 显式检查)。
  49. 验证:`dotnet <file>.cs` 产生预期输出。
  50. 验证:多文件应用包含每个所需 helper 文件,并排除非预期匹配。
  51. 验证:会话结束后清理应用文件和缓存产物。
  52. Pitfall:`.cs` 文件在含 `.csproj` 的目录中时,移到项目目录外,或使用 `dotnet run --file file.cs`。
  53. Pitfall:`#:package` 没有版本时,指定版本 `#:package PackageName@1.2.3`,或用 `@*` 取最新版。
  54. Pitfall:`#:property` 语法错误时,使用 `PropertyName=Value`,`=` 两边无空格、无引号,例如 `#:property AllowUnsafeBlocks=true`。
  55. Pitfall:指令放在 C# 代码之后时,所有 `#:` 指令必须紧跟在可选 shebang 行之后、任何 `using` 指令或其他 C# 语句之前。
  56. Pitfall:helper 文件未编译时,在入口文件添加 `#:include Helper.cs` 或合适 glob。
  57. Pitfall:共享文件需要程序集边界时,用 `#:ref Shared.cs` 而非 `#:include Shared.cs`;如果被引用文件没有入口点,在其中设置 `#:property OutputType=Library`。
  58. Pitfall:宽泛 include 拉入无关文件时,优先窄 include 模式,并用 `#:exclude` 排除 generated、backup 或 experimental 文件。
  59. Pitfall:包含文件中重复指令时,保持 package、property、SDK、include、exclude 指令在入口和包含的 C# 文件之间唯一。
  60. Pitfall:反射式 JSON 序列化失败时,使用带 `JsonSerializerContext` 的源生成 JSON。
  61. Pitfall:出现意外构建行为或版本错误时,file-based apps 会从父目录继承 `global.json`、`Directory.Build.props`、`Directory.Build.targets` 和 `nuget.config`;如果继承设置冲突,把应用移到隔离目录。
  62. 参考更多信息:https://learn.microsoft.com/en-us/dotnet/core/sdk/file-based-apps。

适用边界 · 注意事项