C# · 12月 30, 2021

C#编译/构建增量过程?

我们的解决方案包含大量的C#项目.它们之间存在复杂的依赖关系,例如.项目A / B / C,A依赖于B,B依赖于C.如果我在项目C中更改一个文件,则重新构建解决方案,项目A,B,C将一起重建.

在C中,build包含两个进程,编译和链接.如果我在项目C中更改一个文件,那么我构建解决方案,A和B中的相关文件将被编译(其他文件将不会被编译,它们的.obj将在链接过程中被重用),然后进行链接.

在java中,只需要重新编译项目C中的更改后的文件,其他文件将被保存,然后打包到.jar.它重用以前的工作输出(未更改的文件的.class).

总而言之,C#不会重用任何以前的工作输出.它没有任何中间文件,就像Java的.class和C的.obj一样.所以在这一点上,我觉得C#没有做增量制作过程.一些小的变化将导致大的构建过程.我不明白为什么C#不使用以前的工作输出来加速构建过程.

我不知道我对C#编译/构建过程的理解是否正确.你能帮忙解释一下吗?非常感谢.

解决方法 C#编译器进行增量编译,我不知道你在哪里得到它的意思.也许,由于您的解决方案的复杂性,您不能正确地了解依赖项,而您假设不需要重新编译的项目实际上是必需的.

检查编译器行为的最好方法是创建一个简单的虚拟解决方案,并使用它:

建立:

>创建一个空的Visual Studio C#解决方案.
>添加任何两个项目A和B.
>使项目B成为项目A的参考.
>在B中实现一个类FooInB,并在A BarInA中的另一个类中使用它.

现在可以用这个设置来播放一下:

>编译解决方案.你会看到这两个项目都是编译的.
>再次编译解决方案.您将看到没有一个项目编译,都是最新的.
>更改BarInA中的实现并重新编译.您
会看到只有一个项目编译,A.没有必要
再次编译B,因为没有变化.
>更改FooInB中的实现,最后编译一次.你会看到这两个项目都是编译的.这个行为是正确的,所以B中的任何改变将一定需要A重新编译以确保它指向最新版本B.在理论世界中,C#编译器可以检测B中的变化是否在A中没有后果,因此可以再次优化建筑A,这将是一个噩梦的场景,每个项目都可以引用不同的和过时的装配版本.

也就是说,我想指出,AFAIK,C#编译器只能在项目级执行增量编译.我不知道任何给定的程序集中的类级别上的任何增量编译优化.对编译器的内部工作有更多洞察力的人可能能够澄清这一行为.