我作为C#开发人员度过了我的职业生涯。作为一名学生,我偶尔使用C但没有深入研究它的编译模型。最近我跳上了潮流,开始研究Objective-C。我的第一步只让我意识到我先前存在的知识存在漏洞。
根据我的研究,C / C ++ / ObjC编译需要预先声明所有遇到的符号。我也理解建筑是一个两步的过程。首先,将每个单独的源文件编译为单个目标文件。这些目标文件可能具有未定义的“符号”(通常对应于头文件中声明的标识符)。其次,将目标文件链接在一起以形成最终输出。这是一个非常高级的解释,但它足以满足我的好奇心。但我也希望对C#构建过程有类似的高级理解。
问: C#构建过程如何解决头文件的需求?我想也许编译步骤可以进行两遍?
(编辑:此处跟进问题How do C/C++/Objective-C compare with C# when it comes to using libraries?)
答案 0 :(得分:91)
答案 1 :(得分:37)
我看到这个问题有多种解释。我回答了解决方案内的解释,但让我用我知道的所有信息填写。
“头文件元数据”存在于已编译的程序集中,因此您添加引用的任何程序集都将允许编译器从这些程序集中提取元数据。
对于尚未编译的东西,当前解决方案的一部分,它将进行两遍编译,首先读取命名空间,类型名称,成员名称,即。除了代码之外的一切。然后当它检出时,它将读取代码并编译它。
这允许编译器知道存在什么和不存在什么(在它的宇宙中)。
要查看有效的双程编译器,请测试以下具有3个问题的代码,两个与声明相关的问题以及一个代码问题:
using System;
namespace ConsoleApplication11
{
class Program
{
public static Stringg ReturnsTheWrongType()
{
return null;
}
static void Main(string[] args)
{
CallSomeMethodThatDoesntExist();
}
public static Stringg AlsoReturnsTheWrongType()
{
return null;
}
}
}
请注意,编译器只会抱怨它找不到的两个Stringg
类型。如果你修复了那些,那么它会抱怨在Main方法中调用的方法名称,它无法找到。
答案 2 :(得分:5)
它使用参考程序集中的元数据。它包含一个完整的类型声明,与您在头文件中找到的相同。
它是一个两遍编译器完成其他事情:你可以在一个源文件中使用一个类型,然后再在另一个源代码文件中声明。
答案 3 :(得分:1)
答案 4 :(得分:1)
可以从引用的程序集中获取所有必要的信息。
因此没有头文件,但编译器 需要访问正在使用的DLL。
是的,它是一个2遍编译器但是没有解释它如何获取有关库类型的信息。