C# 7.1引入了一些新的命令行参数来帮助创建“引用程序集”。通过documentation,它输出一个组件:
将其方法体替换为单个throw null体,但包括除匿名类型之外的所有成员。
我找到了an interesting note that it is more stable on changes:
这意味着它的变化频率低于完整程序集 - 许多常见的开发活动不会改变界面,只会改变实现。这意味着增量构建可以更快 - ...
和it is probably necessary for roslyn itself ..
我们将介绍第二个概念,即“参考组件”(也称为骨架组件)。 [---] 它们将用于构建场景。
..无论那些“构建场景”是针对Roslyn的。
据我所知,对于普通的.NET程序集用户来说,这样的程序集可能更小,加载反射速度稍快。好的,但是:
它的用处似乎很小。
所以,我想知道通用程序集生成器方面的事情 - 何时应该考虑明确使用这些新的编译器标志来创建引用程序集?它在Roslyn本身之外是否有任何实际用途?
答案 0 :(得分:1)
这个功能的动机确实是构建场景,但它们并不是特定于Roslyn; 他们 构建方案。
构建项目时,构建引擎(MSBuild)需要确定构建的每个输出是否与其输入相关。例如,如果你没有改变任何东西并且只是连续两次运行构建,那么第二次不需要调用C#编译器:程序集已经是正确的。
参考程序集允许在更多场景中跳过程序集的编译步骤,因此您的构建可以更快。我想一个例子可以帮助说明。
假设您的解决方案包含的B.exe
取决于A.dll
。
B的编译器命令行看起来像
csc.exe /out:B.exe /r:..\A\bin\A.dll Program.cs
它的输入将是
Program.cs
)如果更改A的源并构建解决方案,则编译器必须针对A运行,生成新的A.dll
。然后,由于A.dll
是B编译的输入,因此B也必须重新编译。
使用A的参考组件稍微改变
csc.exe /out:B.exe /r:..\A\bin\ref\A.dll Program.cs
A的输入现在是引用程序集,而不是它的实现/正常程序集。
由于引用程序集小于完整程序集,因此对构建时间的影响很小。但这还不足以证明这一功能。重要的是编译器只关心传入引用的公共API表面。如果程序集的内部实现详细信息已更改,则不需要重新编译引用它的程序集以获取新行为。正如@Hans Passant在评论中提到的那样,这就是.NET Framework本身如何提供兼容的性能改进以及对未更改的用户代码的错误修复。
参考程序集功能的好处来自于使用它们完成的MSBuild工作。假设您更改了A中的内部实现细节但未更改其公共接口。在下一个版本中,
A.dll
(带有已更改的实现)和ref\A.dll
,这与前一个引用程序集相同。ref\A.dll
与之前的输出相同,因此不会将其复制到A的输出文件夹。A.dll
复制到其输出中,并准备好以新行为运行。在大型解决方案中,跳过下游编译的效果会更复杂 - 更改{ProjectName}.Utilities.dll
中的注释不再需要构建所有内容!
许多更改涉及更改公共API表面和内部实现,因此此更改不会加快所有构建,但它确实加快了许多构建。