C#编译/构建是一个增量过程吗?

C#编译/构建是一个增量过程吗?,c#,build-process,C#,Build Process,我们的解决方案包含许多C#项目。它们之间存在复杂的依赖关系,例如项目A/B/C、A依赖于B、B依赖于C。如果我更改项目C中的一个文件,然后重建解决方案,则项目A、B、C将一起重建 在C++中,构建包含两个过程,编译和链接。如果我在项目C中更改了一个文件,那么我构建了解决方案,A和B中的相关文件将被编译(其他文件不会被编译,它们的.obj将在链接过程中被重用),然后执行链接 在java中,只需重新编译C项目中更改的文件,其他文件将保留,然后打包到.jar。它重用以前的工作输出(未更改文件的.cla

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

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

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

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


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

好的。。你实际上走在正确的轨道上。。如果解决方案中有3个项目,则可以将一个项目的引用给另一个项目。这意味着项目A依赖于项目B依赖于项目C

生成项目时,所有生成的文件和DLL(来自生成后事件)最终都会位于该项目的bin文件夹中

因此,当您构建项目A时,项目C将首先构建(因为A->B->C)。项目B使用项目C的内置组件并创建自己的组件。项目A使用B和C的组件并创建自己的组件

因此,如果您只构建项目A,如果引用正确,您将在项目A的bin文件夹中看到B和C的所有构建文件。

C编译器执行增量编译,我不确定您从何处知道它不执行增量编译。也许,由于解决方案的复杂性,您没有正确理解依赖关系,并且您认为不需要重新编译的项目实际上是必要的

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

设置:

  • 创建一个空的Visual Studio C#解决方案
  • 添加任意两个项目,
    A
    B
  • 将项目
    B
    作为项目
    a
    中的参考
  • B
    中实现一个类
    FooInB
    ,并在
    a
    BarInA
    中的另一个类中使用它
  • 现在让我们来看看这个设置:

  • 编译解决方案。您将看到这两个项目都进行了编译
  • 再次编译解决方案。您将看到没有一个项目是编译的,它们都是最新的
  • BarInA
    中更改实现并重新编译。你 将看到仅编译一个项目,
    A
    。没有必要 重新编译
    B
    ,因为没有更改
  • FooInB
    中更改实现并最后编译一次。您将看到这两个项目都进行了编译。此行为是正确的,
    A
    取决于
    B
    ,因此
    B
    中的任何更改都必须重新编译
    A
    以确保它指向
    B
    的最新版本。在一个理论世界中,C#编译器可以检测到
    B
    中的更改是否对
    a
    没有影响,因此可以再次“优化”构建
    a
    ,这将是一个噩梦场景,每个项目都可能引用不同且过时的程序集版本
  • 也就是说,我想指出,实际上,C#编译器只会在项目级别执行增量编译。我不知道在任何给定程序集中有任何类级别的增量编译优化。对编译器的内部工作有更深入了解的人可能能够澄清这种行为。

    你说得有点对

    如果项目A依赖于项目B,那么依赖项目B中的变更确实需要重新编译项目A

    如果项目B依赖于项目C,那么项目B中的变更不会使项目C重新编译

    在Java中,一个类/文件被编译成一个.class文件。因此,当单个文件发生更改时,不需要重新编译整个项目

    在分发之前,这些.class文件被合并到一个.jar中。如果单个.class文件发生更改,则还需要重新组装整个.jar

    在.Net中,您可以立即将项目编译为程序集(.dll或.exe),因此单个文件更改需要重新编译整个程序集

    在使用.jar(或类似.apk的依赖项)运行/调试应用程序的Java环境中也可以看到同样的行为。在开发过程中还需要整个.jar。当单个文件发生更改时,整个项目将重新编译


    您始终可以将项目放置在解决方案之外。并且只在它们生成的.dll中添加一个引用。这将最小化编译时间

    我有一个解决方案,有许多项目,甚至有更多的跨项目参考

    为了简单起见,假设我有一个项目
    A
    B
    C

    • A
      是我的主桌面exe,它引用了
      B
      C
    • B
      包含windows窗体和引用
      C
    • C
      包含业务和数据库逻辑
    我的主要问题是:
    B
    编译大约需要45秒。现在让我们假设我只更改
    C
    中的一小行代码,编译器将编译
    C
    ,然后它将编译
    B
    ,而不是
    a
    因为我主要是在