我已经知道C#提供了internal
修饰符:
internal:类型或成员可由同一程序集中的任何代码访问,但不能由另一个程序集访问。 --- 引自本官方文件
我也明白什么是程序集。它基本上是一个DLL或EXE。
现在,我们如何确定我们所有的内部事物实际上都会编译到同一个程序集中?我问这个问题的原因是因为我从这里得到的印象是构建过程可以非常灵活,不同的源文件可能会编译成不同的程序集:
csc /target:library /out:MathLibraryPart1.DLL Add.cs
csc /target:library /out:MathLibraryPart2.DLL Mult.cs
在某种程度上,我们甚至需要一种方法来检测文件是否在特定程序集中。
换句话说,如果我已经在这里和那里用修饰符编写了我的库internal
然后提交我的代码,但由于构建源代码的方式不同,最终的二进制输出可能会也可能不会按预期工作。这对我来说听起来不对。除非,构建源代码的方式(被迫成为)也是我项目不可或缺的一部分,并且需要签入我的代码存储库。是这样吗?
生成是确定性的,是对解决方案文件和项目文件运行 VS 生成器或 MSBuild 的结果。他们严格定义了生产什么组件,那里没有灵活性。一般规则是"一个 .csproj 文件生成一个程序集"。一个.cs文件属于一个 .csproj。
至于你修改方法或类型的访问以internal
,然后在运行时发现某些东西被破坏了,你可以放心:发现发生在编译时。您的代码甚至无法再编译。
此外,您的二进制"可能有效或可能不起作用"似乎缺少基本的单元测试。添加单元测试,使它们成为构建的一部分,然后您将知道代码是否有效(至少是测试的部分)。集成测试也有帮助。开始使用开发人员测试工具。
另请阅读代码完成。你的很多问题几年前就得到了回答,看到他们一次又一次地回来,我感到很难过。
感谢 @Remus-Rusanu 的提示(和动机),我认为理解这一点的最好方法是做一个动手实验。
//File: foo.cs
namespace Space
{
public class FooClass
{
public static int Foo() {return BarClass.Bar();}
}
}
//File: bar.cs
namespace Space
{
internal class BarClass
{
public static int Bar() {return 123;}
}
}
现在,尝试将这两个文件编译为单独的程序集将无法编译,这是正确的行为:
csc /target:library /out:foo.dll foo.cs
error CS0103: The name 'Bar' does not exist in the current context
将它们编译在一起,您将获得库,然后此 dll 中的所有内部结构将按预期工作。
csc /target:library /out:foobar.dll foo.cs bar.cs
# It will generate foobar.dll
所以这澄清了我之前的问题。是的,我们可以确定"我们所有的内部东西实际上都会编译到同一个程序集中",否则编译尝试就会失败。