C# 我们如何才能确保我们所有的内部内容都会被编译到同一个程序集中呢?

C# 我们如何才能确保我们所有的内部内容都会被编译到同一个程序集中呢?,c#,.net-assembly,internal,C#,.net Assembly,Internal,我已经知道C#提供了内部修饰符: 内部:类型或成员可以由同一程序集中的任何代码访问,但不能从另一个程序集中访问。 ---引自此 我也理解。它基本上是一个DLL或EXE 现在,我们如何确保我们所有的内部内容都会被编译到同一个程序集中呢?我问这个问题的原因是,我得到的印象是,构建过程非常灵活,不同的源文件可能被编译成不同的程序集: csc /target:library /out:MathLibraryPart1.DLL Add.cs csc /target:library /out:MathLib

我已经知道C#提供了
内部
修饰符:

内部:类型或成员可以由同一程序集中的任何代码访问,但不能从另一个程序集中访问。 ---引自此

我也理解。它基本上是一个DLL或EXE

现在,我们如何确保我们所有的内部内容都会被编译到同一个程序集中呢?我问这个问题的原因是,我得到的印象是,构建过程非常灵活,不同的源文件可能被编译成不同的程序集:

csc /target:library /out:MathLibraryPart1.DLL Add.cs
csc /target:library /out:MathLibraryPart2.DLL Mult.cs
到了我们甚至需要的程度


换句话说,如果我已经在这里或那里用
internal
修饰符编写了我的库,然后提交了我的代码,但是最终的二进制输出可能会或可能不会按照预期的方式工作,因为构建源代码的方式不同。我听上去不太对。除非,否则构建我的源代码的方法(被迫)也是我的项目不可分割的一部分,需要检查到我的代码库中。是这样吗?

生成是确定的,是在解决方案文件和项目文件上运行VS builder或MSBuild的结果。它们严格定义了生产的组件,没有灵活性。一般规则是“一个.csproj文件生成一个程序集”。一个.cs文件属于一个.csproj

对于将方法或类型的访问权限修改为
internal
,然后在运行时发现某些内容已损坏,您可以放心:发现发生在编译时。你的代码甚至不会再编译了

此外,二进制代码“可能工作,也可能不工作”似乎缺少基本的单元测试。添加单元测试,使它们成为构建的一部分,然后您将知道代码是否有效(至少是测试的部分)。集成测试也有帮助


另外,阅读。您的许多问题多年前就得到了回答,看到它们一次又一次地出现,我感到很难过。

构建是确定的,是在解决方案文件和项目文件上运行VS builder或MSBuild的结果。它们严格定义了生产的组件,没有灵活性。一般规则是“一个.csproj文件生成一个程序集”。一个.cs文件属于一个.csproj

对于将方法或类型的访问权限修改为
internal
,然后在运行时发现某些内容已损坏,您可以放心:发现发生在编译时。你的代码甚至不会再编译了

此外,二进制代码“可能工作,也可能不工作”似乎缺少基本的单元测试。添加单元测试,使它们成为构建的一部分,然后您将知道代码是否有效(至少是测试的部分)。集成测试也有帮助

另外,阅读。你的许多问题多年前就得到了回答,看到它们一次又一次地出现,我很难过。

感谢@Remus Rusanu的提示(和动机),我认为理解这一点的最好方法是做一个动手实验

//文件:foo.cs
命名空间空间
{
公开课
{
公共静态int Foo(){return BarClass.Bar();}
}
}

//文件:bar.cs
命名空间空间
{
内部类BarClass
{
公共静态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
这澄清了我之前的问题。是的,我们可以确定“我们所有的内部内容实际上都将被编译到同一个程序集中”,因为否则编译尝试将失败。

感谢@Remus Rusanu的提示(和动机),我认为理解这一点的最好方法是做一个动手实验

//文件:foo.cs
命名空间空间
{
公开课
{
公共静态int Foo(){return BarClass.Bar();}
}
}

//文件:bar.cs
命名空间空间
{
内部类BarClass
{
公共静态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

这澄清了我之前的问题。是的,我们可以确定“我们所有的内部内容实际上都将被编译到同一个程序集中”,因为否则编译尝试将失败。

幸运的是,我编写了单元测试。:-)我所说的“可能工作,也可能不工作”,是指“如果使用CLI编译器,我的代码是否可能以不同的方式编译,那么一些内部实体可能会变得不可用?”。所以这个问题。此外,一个C#程序员在开始使用这种语言的前几周愿意考虑这种细节,这难道不是一个好迹象吗?仍然感谢您的提示,我对您的答案投了赞成票。“是否使用CLI编译器”是关键问题。谁会做这样的事,为什么?如果您的项目是端到端的,那么您必须有一个自动化的、可复制的构建过程。虽然它可能由调用CLI编译器的批处理文件组成,但这对于C代码来说是非常不寻常的。所以让我们假设是一个.csproj,然后不必担心CLI。如果您担心以库的形式发布代码,在C#社区中,库是作为预构建程序集使用的,最好以NuGet软件包的形式发布。如果您担心以单个源代码文件的形式发布库,并且消费者错误地使用它们,这是一个不可能捍卫的立场。您绝对不应该嵌入运行时代码来检查基本上是一个编译不好的二进制文件,尤其是当编译器捕获到错误用法时