Visual Studio和C#编译器如何将源代码编译成一个汇编?

390 阅读8分钟

C#是一种已编译的语言。这意味着,当开发者创建C#源文件时,这些文件在运行之前需要被编译。你不能像对待JavaScript或PHP文件那样,编写一个C#文件,然后运行该文件或文件组合。这就是汇编在编译语言中发挥作用的地方。汇编文件是C#编译器读取人类可读的C#源代码文件的结果,然后产生一个应用程序可以使用的文件。事实上,一个C#程序通常由许多汇编文件组成,它们一起工作。


编译一个C#源代码文件

实际上,你不需要一个漂亮的IDE来编写和编译C#程序。当然,这要容易得多,因为像Visual Studio这样的东西会为你做很多繁重的工作。让我们看看如何使用csc.exe程序从命令行中直接使用C#编译器。
c sharp compiler csc

在命令行中,我们可以使用notepad.exe来创建一个简单的keto.cs程序文件。我们将制作一个简单输出 "我喜欢Keto "的程序。在这里看看这个简单的程序。我们完全没有像Visual Studio那样得到任何语法高亮或帮助。
csharp file in notepad

现在,我们想从命令行中直接编译这个源代码文件。csc.exe是我们要使用的程序,它位于C:WindowsMicrosoft.NETFramework>v4.0.30319csc,如图所示。
microsoft csc compiler location

为了编译我们的C Sharp源文件,我们可以简单地从命令行中调用csc.exe程序,并传入我们要编译的文件名。这里我们把keto.cs文件编译成keto.exe文件。
compile csharp file at command line example

爽啊!编译器已经创建了一个可执行文件,现在可以从命令行中运行。事实上,我们刚刚在C#中创建了我们的第一个汇编!是的,它是一个exe文件,但从技术上讲,它可以被称为一个汇编。一个.NET程序集是一个包含编译代码的文件,现在可以在通用语言运行时中执行。下面是我们的程序集的全部内容。

.NET程序集是具有.exe或.dll扩展名的文件。第一种类型是可执行的文件,就像我们刚才看到的那样。Dll文件则有点不同。dll文件意味着它是所谓的动态链接库。Dll文件不像exe文件那样被执行,但它们可以被其他程序加载并运行其中的代码。这些类型的文件经常被用于代码重用。.NET框架是代码重用的一个很好的例子。像.NET中的Console和DateTime这样的普通,都在.NET框架提供的名为mscorlib.dll的程序集内。


全局程序集缓存

.NET程序集是Windows计算机上全球程序集缓存的一部分。全局程序集缓存位于C:WindowsassemblyGAC>中,就像我们在这里看到的那样。
Windows Global Assembly Cache

存储在GAC中的程序集可以被计算机上运行的任何.NET应用程序使用。像mscorlib和其他常见的程序集都在GAC中,为计算机上需要它的任何应用程序提供了一个副本。


在Visual Studio中使用程序集

build visual studio files into an assembly

当在Visual Studio中构建一个解决方案时,所有的源代码文件都被收集在一起并被构建成一个程序集。在这种情况下,它被构建成一个可执行的程序集,或一个扩展名为.exe的文件。这个文件是由C#编译器在bin/Debug目录下创建的。让我们看一看。

C:UsersusersourcereposStocksStocksbinDebug>dir
 Volume in drive C is OSDisk
 Volume Serial Number is F232-B880

 Directory of C:UsersusersourcereposStocksStocksbinDebug

02/05/2019  01:43 PM              .
02/05/2019  01:43 PM              ..
02/06/2019  05:29 PM             5,632 Stocks.exe
02/04/2019  04:46 PM               189 Stocks.exe.config
02/06/2019  05:29 PM            22,016 Stocks.pdb
               3 File(s)         27,837 bytes
               2 Dir(s)  83,911,729,152 bytes free

我们可以看到,Stocks.exe是一个由C#编译器创建的文件。它是一个可以运行的程序集,因为它的扩展名为.exe。其原因是,当我们创建这个项目时,我们选择了创建一个名为Stocks的控制台应用程序。Visual Studio有一堆选项,根据你选择的项目类型进行配置。程序集名称与项目名称相同,所以在这种情况下它是Stocks。

给予程序集的扩展是由输出类型设置控制的。对于Windows应用程序或控制台应用程序,我们将得到.exe扩展名。如果我们选择类库选项,程序集将不再得到一个.exe扩展名,而是一个.dll扩展名。
vs application output type menu

为了搞笑,我们可以把输出类型改为类库,然后再次构建解决方案。现在,当我们查看Debug文件夹中的目录内容时,肯定会看到Stocks.dll而不是Stocks.exe。

C:UsersusersourcereposStocksStocksbinDebug>dir
 Volume in drive C is OSDisk
 Volume Serial Number is F232-B880

 Directory of C:UsersusersourcereposStocksStocksbinDebug

02/08/2019  04:53 PM              .
02/08/2019  04:53 PM              ..
02/08/2019  04:53 PM             5,120 Stocks.dll
02/04/2019  04:46 PM               189 Stocks.dll.config
02/08/2019  04:53 PM            19,968 Stocks.pdb
               3 File(s)         25,277 bytes
               2 Dir(s)  83,904,868,352 bytes free

这种类型的文件是不能直接运行的。事实上,如果我们尝试这样做,我们会从Visual Studio得到一条信息:"一个输出类型为Clas Library的项目不能直接启动。为了调试这个项目,在这个解决方案中添加一个引用库项目的可执行项目。将该可执行项目设置为启动项目"。
choose correct output type in visual studio


转到汇编定义

了解你感兴趣的程序集的一个很好的方法是在Visual Studio中右击程序集名称,然后选择 "转到定义"。在这里,你可以看到我们在Console程序集上点击右键,然后选择 "转到定义"。
visual studio go to definition

然后Visual Studio将打开一个新的窗口,里面有该类中所有可用方法的概要。这不是源代码,而几乎就是一个接口的集合。该文件显示了你可以从Console类中调用什么,就像你在打字时,intellisense试图猜测你想使用什么方法一样。注意在文件的最上面,我们可以看到它使用的是什么程序集。

#region Assembly mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.6.1mscorlib.dll
#endregion

mscorlib assembly


查看项目组件

要查看Visual Studio中某个特定项目所使用的程序集,你可以在解决方案资源管理器中查看,然后点击引用选项。
visual studio solution explorer references

在这个节点下列出了Microsoft.CSharp、System、System.Core、System.Data、System.Data.DataSetExtensions、System.Net.Http、System.xml和System.Xml.Linq等内容。这些是本项目可能引用的其他程序集。当你创建一个新项目时,Visual Studio会自动包含其中的许多组件,因为它试图访问许多应用程序使用的常见组件。即使你不使用引用节点中的一些程序集,这也不是问题,因为.NET只有在你在程序中实际使用一个程序集的类时才会加载该程序集。


用对象浏览器仔细观察

为了了解更多关于一个特定程序集的信息,你也可以使用对象浏览器来深入了解可用的内容。例如,让我们在对象浏览器中看一下System.Net.Http。
view in object browser

通过这个,System.Net.Http在对象浏览器中打开,我们可以看到该程序集中的所有功能。我们可以看到几个类,如HttpClient、HttpClientHandler、HttpCompletionOption、HttpContent,等等。当然在这些类里面都有属性和方法。检查那个HttpMethod类可以看到几个属性,如Delete、Get、Head、Method、Options、Post、Put和Trace。然后,如果我们对GET请求感兴趣,例如,我们可以深入研究HttpMethod,然后选择Get,并注意到我们所提供的信息。

public static System.Net.Http.HttpMethod Get { get; }
    Member of System.Net.Http.HttpMethod

Summary:
Represents an HTTP GET protocol method.

Returns:
Returns System.Net.Http.HttpMethod.

System-Net-Http in Object Browser


在你的项目中添加引用

visual studio add reference 在.NET框架中,有这么多的程序集,几乎不可能全部了解它们。机会是,你不需要从头开始创建很多东西,因为大多数常见的问题已经被一个可用的程序集解决了。例如,假设你想在你的应用程序中添加对图表的支持。继续添加对System.Web.DataVisualization组件的引用。
Reference Manager Web Data Visualization

这些命名空间集合了成百上千的方法和属性,用于创建和渲染你可能需要的任何类型的图表,如柱状图、饼状图和各种自定义图表。


什么是C#中的程序集摘要

在本教程中,我们学习了Visual Studio和C#编译器如何将我们的源代码编译成一个汇编。程序集的名称将与项目的名称相同。由此产生的程序集将有一个.exe或.dll的扩展名,这取决于你是要建立一个直接执行的程序,还是一个类库。我们还看到,大多数应用程序都需要一个以上的程序集,我们还学习了如何添加对其他程序集的引用。在.NET中,开发者创建的所有类型都将存在于一个程序集中。