如果您更愿意使用其他某种语言,将代码转换为您所使用的语言相对来说比较简单。但是 Dr. GUI 这个家伙却没有时间完成这项工作。如果有人想要进行这项工作,Dr. GUI 也许能够提供到您的转换后的代码的链接——但这并非承诺。
运行 Beta 1 版所需的条件
运行 Visual Studio.NET 的 Beta 1 版所需的条件相当简单:计算机的操作系统为 Windows 2000、Windows NT® 4.0、Windows 98 或 Windows Me。(可能会在以后的 Beta 版本中支持其他操作系统,例如 Whistler Beta 版和 Windows 95。)计算机还必须具备相当快的运算速度(要求 PII/450,建议使用 PIII/733)、1 GB 或 2 GB 硬盘空间、128 MB 内存(建议使用 256 MB 内存),至少有 Super VGA (SVGA) 视频和 CD-ROM 或 DVD-ROM 驱动器。如果您只想安装 .NET 框架SDK,CPU 和内存的要求可以稍微低一些;硬盘空间的需求可显著降低(只需 100-200 MB 就足够了)。
您还需要安装 Internet Explorer 5.5 (http://www.microsoft.com/windows/ie/)、MDAC (ADO) 2.6 (http://www.microsoft.com/data/download.htm) 和 Microsoft Web 服务器。(在控制面板中,单击“添加/删除程序”,然后单击“添加/删除 Windows 组件”。)如果您有 Visual Studio.NET 的 CD,安装程序将自动更新 Internet Explorer 和 MDAC。
安装说明建议您在非生产用途的计算机上安装。Dr. GUI 没有发现 Visual Studio.NET 和/或 .NET 框架与其他软件之间的不良影响,但是他赞成这个建议:不要在您赖以工作的计算机上冒险使用 Beta 版的软件。事实上,Dr. GUI 在另一台日常很少用的计算机上安装了 .NET 框架。(尽管博士想过当一个冒险者,在他的膝上型电脑上安装。)
获得 .NET 的方式
最容易获得 Visual Studio.NET 和 .NET 框架SDK 的地方是 MSDN .NET 开发人员中心 (http://msdn.microsoft.com/net/)。
如果仅仅是想要签出 .NET 框架,且具有很快的连接,那么您可以免费下载它(很大,大概 111 MB)。您也可以免费定购它,但您需要负担 CD 的邮寄费用。.NET 框架SDK 包含编译器(甚至 C#!),但不包括集成的开发环境 (IDE)。
但是如果您想要定购 .NET 框架SDK 的 CD,请定购整个 Visual Studio.NET CD 集(其中包含三张 CD,您还是只需负担邮寄费用)。如果您是 MSDN 全球订户,则只能下载 Visual Studio.NET,它的大小约为 1.5 GB,所以必须有真正快速的 Internet 连接。
安装
绝大部分安装都简单易行,只需单击适当的安装程序或 URL 就可以了。安装程序易于理解而又方便。
不过,还是有一个小技巧:安装 .NET 框架SDK 时,系统将询问您是否注册环境变量,以便可以从命令行生成。请确保选择了这个复选框来注册环境变量,这样才能使用命令行工具。
编写 .NET 程序
Visual Studio.NET 的设计目的是使 .NET 编程变得更简单,除此之外,诸如自动完成语句和拖放窗体编辑之类的功能,使得使用不熟悉的 API 集变得极其简单。
我们将要使用 Visual Studio,但是现在博士要求大家用旧的方式做事:在记事本(或 Visual Studio,如果愿意)中编写源文件,将其保存到磁盘上,然后编译并从命令行运行。这些工作只需要 .NET SDK,而不需要 Visual Studio.NET。使用命令行工具也可以使我们有机会看到产生了什么文件和熟悉某些命令行工具。
注意,因为从 Beta 1(当前版本)到最终上市的版本计划会对 .NET API 做一些重要的改动。所以,您编写的 Beta 1 版代码必须要为在 Beta 2 或最终版本下运行而进行一些修改。但是,现在开始学习的重要概念是不会改变的,所以现在的学习并非徒劳无益。
如何拼写
在 .NET 程序中使用大小写的惯例也许和您所用过的其他语言不同。但是,.NET 的规则极其简单:所有非参数名的标识符和私有域的名称,其每个词的首字母大写,包括第一个。(Microsoft 建议将所有域都设为私有,但是它们也许要通过一个属性公开。)对于参数名称和私有域的名称,其每个词的首字母大写,第一个除外。您必须了解这些规则,因为 .NET 框架名称遵循这些规则,并且某些语言(如 C#)是区分大小写的。
所以,主要的输出函数名为 System.Console.WriteLine,严格遵循大小写规则。System.Console.WriteLine 的格式字符串参数名为 formatString,而不是 FormatString。但是字符串长度属性的名称是 StrLen,而不是 strLen。
对于 Dr. GUI,最困难的事是要记住使用 Main 而不是 main。
Hello World.NET
现在,没有问题了,这里是 .NET 最简单的“Hello World”: class MyApp {
public static void Main() {
System.Console.WriteLine("Hello, world! (1)");
}
}
类中的所有对象
您首先注意到的可能是 Main 函数是类的成员。在 .NET 中,所有方法必须是类或结构的成员。(下次,我们将详细讨论结构。)这是因为在 .NET 中,组织的基本单位是类型(即类或结构)。Visual C++.NET 的托管 C++ 扩展允许您可以在类之外公开地编写变量和函数,但在类中也可以编写变量和函数:隐含的全局类。
看!没有头文件!
不但是类中的所有对象,而且类声明都完成了。除了 C#(和大多数 .NET 语言)源代码的源以外,没有头文件、IDL 文件或其他任何文件。所需要说明类的东西就是类本身。
那么,如果您使用不在源文件中的其他类,会发生什么情况呢?编译器如何明白这个类中的内容?
答案是编译器读取包含您所使用的类的程序集中的元数据。程序仅仅隐式地使用 System.Object(因为所有对象来自于 System.Object)。C# 编译器自动转到 mscorlib.dll 程序集以从中获得元数据,所以它能够获得需要用于 System.Object 的信息。如果使用不同程序集中的类,请在 C# 编译器 (CSC) 命令行中使用 /r 选项以指定程序集,例如: csc /r foo.dll hello.cs
顺便提一句,模块是一个可执行文件,即应用程序或库。它的扩展名通常是 .exe 或 .dll。程序集是一个或多个模块的集合。程序集中的一个文件具有程序集的清单,或该程序集中文件的列表。程序集是可以被部署和版本化的可执行代码的最小单位(当以后我们查看程序集的清单时,您会注意到只有程序集有版本号)。
Main 很特殊
下一步您可能会注意到在 Main: public 和 static 上的修饰符。对 C# 中的成员的缺省访问控制是 private,因此我们需要声明 Main: public 以使它可以在运行时被调用。Main 是 static,也可以说是类方法,而不是实例方法。因此运行时可以调用它而不用关心创建 MyApp 对象并将该对象的 this 指针传递给 Main 对象。注意,这里我调用了 MyApp,您可以调用类中的任何对象。这个版本的 Main 不带任何参数并且不返回任何东西,由 void 的返回类型表示。(可以编写带有其他参数的 Main 并返回值)。
最后,我们调用 WriteLine 方法编写字符串。我已经选择使用函数 System.Console.WriteLine 的完全限定名。WriteLine 是一个 System 名称空间中的 Console 类的 static 方法(和 Main 一样)。
减少键入
经常输入完全限定的类名是很麻烦的事情,所以 C# 允许您指定用 using 语句查找的名称空间。例如: using System;
class MyApp {
public static void Main() {
Console.WriteLine("Hello, world! (2)");
}
}
因为编译器搜索 System 名称空间和 local 名称空间,所以我们不必在 Console.WriteLine 的调用中指定 System。这并不是一个大的胜利,但是当您有许多对象引用和方法调用时,它非常方便。在下面的程序中您会看到这一点。
等一下!别走开!
在某些情况下(例如从文件管理器中运行 hello.exe),命令窗口可能会在您看到输出之前消失。要防止发生这种情况,请调用 Console 的 ReadLine 方法从键盘上读取,这将导致程序在您按 ENTER 键之前暂停。(我们将始终将它作为控制台应用程序的 Main 中的最后一个语句。)
程序如下所示: using System;
class MyApp {
public static void Main() {
Console.WriteLine("Hello, world! (3)");
Console.ReadLine(); // 等待直到按 Enter 键;最后一行
}
}
看到了吗?您可以在 C# 中交换!
正如博士所提到的,与其他一些语言不同,您可以在 C# 中编写交换两个变量的函数。
这是一个交换两个整型变量内容的 C# 程序: using System;
class SwapInts {
public static void Main() {
Int32 i = 1, j = 2;
Console.WriteLine("i 是 {0}, j 是 {1}", i, j);
Swap(ref i, ref j);
Console.WriteLine("i 是 {0}, j 是 {1}", i, j);
Console.WriteLine(
"i 仍是 {1:####},j 仍是 {0:####}",
j, i
);
Console.ReadLine();
}
static void Swap(ref Int32 a, ref Int32 b) {
Int32 t = a;
a = b;
b = t;
}
}
这里要注意一些事情。第一,博士已经选择使用 .NET 框架类型 System.Int32(Int32 的全名)而不是 C# 类型 int。因为 C# 中的 int 只是 System.Int32 的一个简单别名,此外没有任何差别。但是,Dr. GUI 希望使用 .NET 框架类型而不是特定于 C# 的类型,这使得将示例转换为 C# 以外的语言要容易一点。这些类型在所有语言中都是一致的。(当 Dr. GUI 用 C# 为 C# 程序员编写代码时,他趋向于使用 C# 类型,因为它们使他想起 C/C++ 类型,并且感觉很好。)
下一步,注意 Console.WriteLine 所提供的灵活的格式。变量被插入到输出字符串中,在括号中表达式 {0} 和 {1} 的位置。数字 0 和 1 代表将要被格式化的参数的位置。第一个参数编号为零而不是一。(数组编号也是从零开始的,这就是为什么这个专栏叫做 GUI.NET #0,而不是 #1)。您会注意到博士在最后的 WriteLine 语句中切换了变量。将格式字符串转换到具有不同文法的语言时,能够切换次序是非常重要的,即您可以改变格式字符串而不用改变调用。另外,还可以在括号中加入其他信息,正如在最后一条 WriteLine 语句中。这种格式化机制对于类型来说也是可扩充的。
最后,请注意最重要的一点:在 Swap 的调用和函数声明中,通过引用传递的参数用 ref 来标记。这就告诉了 C# 编译器我们想要在调用方法时将交换 i 和 j 的方式。如果不使用 ref 标记,则要交换由值传递值时生成的副本(您可以试一下删除 ref 的全部四个实例,然后亲自查看结果)。
实践与探讨

让我们动手吧!
一旦安装了 .NET,您就可以使用记事本或 Visual Studio 创建包含前面的“Hello World”程序之一的文件。创建一个空的子目录,将文件保存到该子目录中,并命名为 hello.cs(CS 表示为 C# 文件)。
下一步,打开命令提示并更改到正在使用的目录。键入“csc hello.cs”命令来编译该程序。如果在目录中查看,您将发现已经创建了 hello.exe 文件。键入“hello”执行该文件,控制台窗口将显示“Hello, World!”。
可执行文件的内容
列出目录的内容,请注意只有两个文件:hello.cs 和 hello.exe。Hello.exe 是一个非常小的文件,只有 3 KB 左右。真简单。
但是,hello.exe 文件中有些什么?这就不那么简单了。有一个存根加载器,即很小的本机机器语言程序,它可加载 .NET Runtime 并给予其控制权以便使它开始执行您的程序。
但是两个重要的部分是元数据和 IL 中的代码,元数据向 Common Language Runtime 和可能引用程序中的类型的编译器解释该程序。(您可能会想起 IL 是 .NET Runtime 的机器语言。)当 Runtime 即将开始执行每种方法时,它将 IL 转换为本机代码,然后执行本机代码。.NET 从来不解释 IL,它总是将 LI 编译成本机代码。
如何查看元数据和 IL?使用 IL 反汇编 (ILDASM) 工具会使该操作变得非常简单。只要在命令提示下输入“ILDASM hello.exe”(假设 hello.exe 文件在当前目录下)就可以了。您可以看到一个如下显示的窗口。

图 1:ILDASM 窗口
最初,“hello.exe”之下的目录树显示两个部分:清单和类 MyApp。由于模块 hello.exe 有一个清单,所以我们知道它就是程序集的说明文件。在这种情况下,程序集仅包含一个模块文件 hello.exe。
清单
双击清单将看到元数据的一小部分,这部分说明了这个程序集(应用程序或组件)中包含的模块(文件)。对于第三个 hello.exe 程序,它看起来如下: .assembly extern mscorlib {
.originator = (03 68 91 16 D3 A4 AE 33 )
.hash = (52 44 F8 C9 55 1F 54 3F 97 D7 AB AD E2 DF 1D E0
F2 9D 4F BC )
.ver 1:0:2204:21
}
.assembly hello as "hello" {
// --- 下面的自定义属性是自动添加的
// 不要取消注释 -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor (bool,
bool) = ( 01 00 00 01 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module hello.exe
// MVID: {59365AA0-B469-4359-9BAF-4840A9257C61}
这个元数据声明程序集 hello 的版本为 0.0.0.0,包含模块 hello.exe,并且使用 1.0.2204.21 版本的 mscorlib 程序集(.NET Runtime 主 DLL)。模块版本标识符 (MVID) 是一个包含此版本模块 hello.exe 的 ID 的全局唯一标识符 (GUID)。
模块元数据
如果按下 Ctrl+M 组合键,您将看到更多的元数据,这次是模块的元
上一页 [1] [2]
|