Skip to content

第 2 章:运行第一个示例

本章目标

  • 跑通主案例
  • 确认生成器真的在工作
  • 学会去哪里看生成出来的代码

先看现象

这章不只看“运行命令”,还要把运行现象和源码位置对上。

主案例在仓库中的目录是:

  • sample/01-tostring-generator

这个目录下有一个示例工程 ToStringGenerator.Sample。当它运行时,你会看到 PersonEmployeeContainer<string> 这些类型都打印出了 ToString() 结果。

重点是:这些类型里很多都没有手写 ToString()

再看代码

程序入口在:

  • sample/01-tostring-generator/ToStringGenerator.Sample/Program.cs

先看最关键的一段:

csharp
var person = new Person
{
    Name = "张三",
    Age = 30
};
Console.WriteLine(person.ToString());

这段代码的重点不是 Console.WriteLine,而是 Person 明明没有手写 ToString(),这里却能直接调用。

建议直接在仓库根目录执行:

powershell
dotnet run --project .\sample\01-tostring-generator\ToStringGenerator.Sample\ToStringGenerator.Sample.csproj

如果一切正常,你会看到类似下面的输出:

text
Person { Name = 张三, Age = 30 }
Employee { Name = 李四, Department = 技术部, EmployeeId = 1001, Salary = 15000.50 }
...

你现在先不用逐字对照输出内容,只要抓住一个事实:编译后的程序确实调用到了生成器补出来的方法。

去哪里看生成的代码

很多新手以为生成器既然“生成了代码”,就应该在项目源文件目录里多出一个 .cs 文件。通常不是这样。

优先去看:

  • sample/01-tostring-generator/ToStringGenerator.Sample/obj/Debug/net8.0/generated

这是构建过程中的中间产物目录,很多生成文件会出现在这里。

例如 Person.g.cs 的核心内容大致是:

csharp
public partial class Person
{
    public override string ToString()
    {
        return $"Person {{ Name = {Name?.ToString() ?? "null"}, Age = {Age} }}";
    }
}

把它和 SimpleClass.cs 对起来看,你就能明白“编译阶段额外补代码”到底是什么意思。

如果你用的是 IDE,也可以尝试在项目树里看:

  • Analyzers
  • Generated Files

如何验证

按下面顺序做:

  1. 打开 sample/01-tostring-generator/ToStringGenerator.Sample/Program.cs
  2. 执行 dotnet run --project .\sample\01-tostring-generator\ToStringGenerator.Sample\ToStringGenerator.Sample.csproj
  3. obj/.../generated 目录找生成出来的 .g.cs
  4. 随便打开一个,比如 Person.g.cs,确认里面真的有 ToString()

如果你能完成这四步,这一章就算真正过了。

如果你还缺“整张源码地图”,直接跳去看 源码导读

常见误解

  • 误解 1:看不到生成文件,说明生成器没生效
    • 不一定,先看 obj 或 IDE 的生成文件节点
  • 误解 2:只要项目能运行,就说明生成器配置完全正确
    • 也不一定,最好亲自去看生成文件
  • 误解 3:输出结果和手写代码没区别,就没必要学源生成器
    • 恰恰相反,重点就在于“效果相同,但维护方式完全不同”

本章新名词

  • obj
  • Generated Files
  • Analyzer 引用

本章小结

这一章最重要的是建立直觉:编译后真正参与运行的代码,比你手写的更多。

下一章我们就来解释,这个案例为什么要拆成三个工程,以及它们是怎么协作的。

上一章 | 返回主教程目录 | 下一章:理解三工程结构

基于当前仓库文档副本构建的 VitePress 站点