C与.NET框架编程基础
立即解锁
发布时间: 2025-08-21 00:06:02 阅读量: 2 订阅数: 8 


C#编程基础与实战技巧
# C#与.NET框架编程基础
## 1 .NET框架诞生背景
在20世纪90年代末,使用微软平台进行Windows编程已分裂为多个分支。大多数程序员使用Visual Basic(VB)、C或C++。一些C和C++程序员使用原始的Win32 API,但大多数使用微软基础类库(MFC),还有一些人转向了组件对象模型(COM)。
然而,这些技术都存在各自的问题:
- **Win32 API**:非面向对象,使用起来比MFC需要更多的工作。
- **MFC**:虽然是面向对象的,但存在不一致性且逐渐过时。
- **COM**:概念上简单,但实际编码复杂,需要大量繁琐、不优雅的代码。
此外,这些编程技术主要用于开发桌面代码,而不是面向互联网编程。当时,Web编程只是事后的考虑,与桌面编程看起来非常不同。
为了解决这些问题,我们需要一个全新的、集成的、面向对象的开发框架,以恢复编程的一致性和优雅性。微软为此着手开发一个满足这些目标的代码执行环境和代码开发环境。
## 2 微软.NET框架的引入
2002年,微软发布了.NET框架的第一个版本,旨在解决旧问题并满足下一代系统的目标。.NET框架比MFC或COM编程技术更加一致和面向对象,具有以下特点:
- **多平台支持**:该系统可在广泛的计算机上运行,从服务器和桌面机到PDA和手机。
- **遵循行业标准**:使用行业标准的通信协议,如XML、HTTP、SOAP和WSDL。
- **安全性高**:即使存在来自可疑来源的代码,系统也能提供更安全的执行环境。
### 2.1 .NET框架的组成
.NET框架由三个组件组成:
| 组件 | 功能 |
| ---- | ---- |
| 公共语言运行时(CLR) | 管理程序的运行时执行,包括内存管理、代码安全验证、代码执行、线程管理、异常处理和垃圾回收等。 |
| 编程工具 | 包括编码和调试所需的一切,如Visual Studio集成开发环境、.NET兼容的编译器(如C#、VB .NET、JScript、F#、IronRuby和托管C++)、调试器以及Web开发服务器端技术(如ASP.NET或WCF)。 |
| 基类库(BCL) | 一个大型的类库,可供.NET框架使用,也可在自己的程序中使用。 |
### 2.2 .NET框架带来的改进
#### 2.2.1 面向对象的开发环境
CLR、BCL和C#设计为完全面向对象,并作为一个集成良好的环境运行。该系统为本地程序和分布式系统提供了一致的面向对象编程模型,还为桌面应用程序编程、移动应用程序编程和Web开发提供了软件开接口,适用于从服务器到手机的广泛目标。
#### 2.2.2 自动垃圾回收
CLR有一个垃圾回收器(GC)服务,可自动管理内存:
- 自动从内存中移除程序不再访问的对象。
- 减轻了程序员传统上必须执行的任务,如内存释放和查找内存泄漏,因为查找内存泄漏可能既困难又耗时。
#### 2.2.3 互操作性
.NET框架设计用于不同.NET语言之间、与操作系统或Win32 DLL以及COM之间的互操作性:
- **.NET语言互操作性**:允许使用不同.NET语言编写的软件模块无缝交互。例如,一个用一种.NET语言编写的程序可以使用甚至继承另一种.NET语言编写的类,只要遵循一定的规则。由于其能够轻松集成不同编程语言产生的模块,.NET框架有时被描述为语言无关的。
- **平台调用(P/Invoke)**:允许为.NET编写的代码调用和使用非.NET编写的代码,例如可以使用从标准Win32 DLL导入的原始C函数,如Windows API。
- **与COM的互操作性**:.NET框架软件组件可以调用COM组件,COM组件也可以调用.NET组件,就像它们本身就是COM组件一样。
#### 2.2.4 无需COM
.NET框架使程序员摆脱了COM的遗留问题。作为C#程序员,无需使用COM,因此无需处理以下事项:
- **IUnknown接口**:在COM中,所有对象必须实现IUnknown接口;而在.NET中,所有对象都派生自一个名为object的单一类。接口编程仍然是.NET的重要组成部分,但不再是核心主题。
- **类型库**:在COM中,类型信息以.tlb文件的形式保存在类型库中,与可执行代码分离;在.NET中,程序的类型信息与代码捆绑在程序文件中。
- **引用计数**:在COM中,程序员必须跟踪对象的引用数量,以确保它不会在错误的时间被删除;在.NET中,GC会跟踪引用并在适当的时候移除对象。
- **HRESULT**:COM使用HRESULT数据类型返回运行时错误代码;.NET不使用HRESULT,而是所有意外的运行时错误都会产生异常。
- **注册表**:COM应用程序必须在系统注册表中注册,该注册表保存着操作系统和应用程序的配置信息;.NET应用程序无需使用注册表,这简化了程序的安装和卸载。
#### 2.2.5 简化部署
部署为.NET框架编写的程序比以前容易得多,原因如下:
- .NET程序无需在注册表中注册,在最简单的情况下,只需将程序复制到目标机器上即可运行。
- .NET提供了并行执行功能,允许同一台机器上存在不同版本的DLL,这意味着每个可执行文件都可以访问为其构建的DLL版本。
#### 2.2.6 类型安全
CLR检查并确保参数和其他数据对象的类型安全,即使是在不同编程语言编写的组件之间。
#### 2.2.7 基类库
.NET框架提供了一个广泛的基类库(BCL,有时也称为框架类库 - FCL),可以在编写自己的程序时使用。其类别包括:
- **通用基类**:为广泛的编程任务提供强大的工具集,如文件操作、字符串操作、安全和加密。
- **集合类**:实现列表、字典、哈希表和位数组等。
- **线程和同步类**:用于构建多线程程序。
- **XML类**:用于创建、读取和操作XML文档。
### 2.3 编译过程
#### 2.3.1 编译为通用中间语言(CIL)
.NET语言的编译器将源代码文件编译成一个称为程序集的输出文件。程序集可以是可执行文件或DLL,其中的代码不是本机机器代码,而是一种称为通用中间语言(CIL)的中间语言。程序集包含以下内容:
- 程序的CIL代码
- 程序中使用的类型的元数据
- 对其他程序集的引用的元数据
中间语言的缩写随着时间的推移有所变化,你可能还会遇到中间语言(IL)和微软中间语言(MSIL)这两个术语,它们在.NET的初始开发和早期文档中经常使用。
#### 2.3.2 编译为本机代码并执行
程序的CIL直到被调用运行时才会编译成本机机器代码。在运行时,CLR执行以下步骤:
```mermaid
graph LR
A[检查程序集的安全特性] --> B[分配内存空间]
B --> C[将程序集的可执行代码发送到即时(JIT)编译器]
C --> D[JIT编译器将部分代码编译为本机代码]
D --> E[缓存编译后的代码]
```
- 检查程序集的安全特性。
- 分配内存空间。
- 将程序集的可执行代码发送到即时(JIT)编译器,该编译器将部分代码编译为本机代码。
程序集中的可执行代码仅在需要时由JIT编译器编译,然后进行缓存,以便在程序后期再次需要执行时使用。这意味着在执行过程中未被调用的代码不会编译为本机代码,而被调用的代码只需编译一次。
一旦CIL编译为本机代码,CLR将在运行时管理它,执行诸如释放孤立内存、检查数组边界、检查参数类型和管理异常等任务。这里引入了两个重要术语:
- **托管代码**:为.NET框架编写的代码称为托管代码,需要CLR。
- **非托管代码**:不在CLR控制下运行的代码,如Win32 C/C++ DLL,称为非托管代码。
微软还提供了一个名为本机映像生成器(Ngen)的工具,它可以将程序集转换为当前处理器的本机代码。经过Ngen处理的代码在运行时可以避免JIT编译过程。
### 2.4 公共语言运行时(CLR)
CLR是.NET框架的核心组件,位于操作系统之上,管理程序的执行,并提供以下服务:
- 自动垃圾回收
- 安全和认证
- 通过访问BCL提供广泛的编程功能,包括Web服务和数据服务等。
### 2.5 公共语言基础结构(CLI)
每种编程语言都有一组表示整数、浮点数、字符等对象的内在类型。历史上,这些类型的特征在不同的编程语言和平台之间有所不同。例如,整数的位数因语言和平台而异。
这种缺乏统一性使得不同语言编写的程序和库之间难以良好协作。为了实现有序和协作,需要一套标准。公共语言基础结构(CLI)就是这样一套标准,它将.NET框架的所有组件连接成一个连贯、一致的系统。它规定了系统的概念和架构,并指定了所有软件必须遵循的规则和约定。
### 2.6 CLI的重要部分
虽然大多数程序员不需要了解CLI规范的细节,但应该熟悉公共类型系统(CTS)和公共语言规范(CLS)的含义和目的。
- **公共类型系统(CTS)**:定义了托管代码中必须使用的类型的特征。一些重要方面包括:
- 定义了丰富的内在类型集,每种类型都有固定的特定特征。
- .NET兼容的编程语言提供的类型通常映射到这个定义的内在类型集的某个特定子集。
- 所有类型都派生自一个名为object的公共基类。
- **公共语言规范(CLS)**:指定了.NET兼容的编程语言的规则、属性和行为,主题包括数据类型、类构造和参数传递。
## 3 简单的C#程序示例
下面通过一个简单的C#程序来初步了解C#编程。
### 3.1 代码示例
以下是一个名为`SimpleProgram.cs`的简单C#程序:
```csharp
using System;
namespace Simple
{
class Program
{
static void Main()
{
// This is a single-line comment
Console.WriteLine("Hi there!");
}
}
}
```
### 3.2 代码逐行解释
| 行号 | 描述 |
| ---- | ---- |
| 1 | 告诉编译器该程序使用`System`命名空间中的类型。 |
| 3 | 声明一个新的命名空间`Simple`,新命名空间从第4行的左花括号开始,到第12行的右花括号结束,此部分内声明的任何类型都是该命名空间的成员。 |
| 5 | 声明一个新的类类型`Program`,第6行和第11行的花括号内声明的任何成员构成这个类。 |
| 7 | 声明一个名为`Main`的方法作为`Program`类的成员,在这个程序中,`Main`是`Program`类的唯一成员,它是编译器作为程序起点的特殊函数。 |
| 9 | 包含一个简单的语句,构成`Main`方法的主体。简单语句以分号结尾,该语句使用`System`命名空间中的`Console`类将消息打印到屏幕上的窗口。如果没有第1行的,编译器将不知道在哪里找到`Console`类。 |
### 3.3 编译方法
可以使用Visual Studio或命令行编译器来编译该程序。使用命令行编译器时,在命令窗口中使用以下简单命令:
```sh
csc SimpleProgram.cs
```
当代码编译并执行时,它将在屏幕上的窗口中显示字符串“Hi there!”。
通过这个简单的示例,我们对C#程序的结构和基本组成部分有了初步的了解。后续可以在此基础上深入学习C#编程的更多知识。
## 4 C#编程基础概念
### 4.1 标识符和关键字
在C#中,标识符是用来命名各种编程元素的名称,如类名、方法名、变量名等。而关键字则是C#语言中具有特殊意义的保留字,不能将其用作标识符。例如,在上述的`SimpleProgram`中,`using`、`namespace`、`class`、`static`、`void`等都是关键字。
### 4.2 `Main`:程序的起点
`Main`方法在C#程序中具有特殊的地位,它是程序执行的起始点。在`SimpleProgram`中,`Main`方法是`Program`类的唯一成员,当程序运行时,首先会执行`Main`方法中的代码。`Main`方法有几种不同的签名形式,常见的有:
```csharp
static void Main()
{
// 代码逻辑
}
static void Main(string[] args)
{
// 代码逻辑
}
static int Main()
{
// 代码逻辑
return 0;
}
static int Main(string[] args)
{
// 代码逻辑
return 0;
}
```
- `static void Main()`:无参数,不返回值。
- `static void Main(string[] args)`:接受一个字符串数组作为命令行参数,不返回值。
- `static int Main()`:无参数,返回一个整数作为程序的退出码。
- `static int Main(string[] args)`:接受命令行参数,返回一个整数作为程序的退出码。
### 4.3 空白字符
在C#中,空白字符(如空格、制表符、换行符等)通常用于提高代码的可读性,编译器一般会忽略它们。例如,在`SimpleProgram`中,代码的缩进和换行只是为了让代码更易读,对程序的执行没有影响。
### 4.4 语句
语句是C#程序中执行操作的基本单位,通常以分号结尾。在`SimpleProgram`中,`Console.WriteLine("Hi there!");`就是一个简单的语句,它使用`Console`类的`WriteLine`方法将字符串输出到屏幕上。
### 4.5 程序的文本输出
在C#中,可以使用`Console`类的方法来实现文本输出。常见的方法有:
- `Console.WriteLine()`:输出一行文本,并在末尾添加换行符。
- `Console.Write()`:输出文本,不添加换行符。
例如:
```csharp
using System;
class Program
{
static void Main()
{
Console.Write("Hello, ");
Console.WriteLine("World!");
}
}
```
上述代码会先输出`Hello, `,然后在同一行接着输出`World!`并换行。
### 4.6 注释:代码注解
注释是用来对代码进行解释和说明的,编译器会忽略注释内容。在C#中有两种常见的注释方式:
- **单行注释**:以两个连续的斜杠`//`开头,从这两个斜杠到行末的所有内容都是注释。例如在`SimpleProgram`中,`// This is a single-line comment`就是单行注释。
- **多行注释**:以`/*`开头,以`*/`结尾,可以跨越多行。例如:
```csharp
/*
这是一个
多行注释
示例
*/
```
## 5 总结
通过上述内容,我们对C#和.NET框架有了较为全面的了解。从.NET框架的诞生背景、组成和优势,到C#程序的基本结构、编译过程以及编程基础概念,这些知识为进一步深入学习C#编程奠定了坚实的基础。
以下是对整个知识体系的一个简单总结表格:
| 主题 | 关键内容 |
| ---- | ---- |
| .NET框架诞生背景 | 20世纪90年代末Windows编程技术存在问题,需要新的开发框架 |
| .NET框架组成 | 公共语言运行时(CLR)、编程工具、基类库(BCL) |
| .NET框架优势 | 面向对象、自动垃圾回收、互操作性、简化部署、类型安全等 |
| 编译过程 | 编译为通用中间语言(CIL),运行时编译为本机代码 |
| C#编程基础 | 标识符和关键字、`Main`方法、空白字符、语句、文本输出、注释 |
同时,我们可以用一个mermaid流程图来概括C#程序的编译和执行过程:
```mermaid
graph LR
A[C#源代码文件] --> B[编译器]
B --> C[生成程序集(CIL代码)]
C --> D[运行时CLR]
D --> E[检查安全特性]
E --> F[分配内存]
F --> G[JIT编译器编译为本机代码]
G --> H[程序执行]
```
希望这些内容能帮助你更好地理解C#和.NET框架编程,开启编程之旅!
0
0
复制全文
相关推荐






