C#主要包含两种条件语句:IF语句和Switch语句。
l if(表达式)
l {
l 语句块;
l }
l if(表达式)
l {
l 语句块1;
l }
l else
l {
l 语句块2;
l }
l if(表达式1)
l {
l 语句块1;
l }
l else if(表达式2)
l {
l 语句块2;
l }
l else
l {
l 语句块3;
l }
l Switch(表达式)
l {
l case 表达式的值1;
l {
l 语句1;
l }
l case表达式的值2;
l {
l 语句2;
l }
l ……
l default:
l {
l 语句default;
l }
l }
l C#中共有四种循环语句:
l for语句、foreach语句、while语句和do语句。
跳转语句的作用是使函数内的程序无条件的改变控制权,即在程序间进行控制转移。跳转语句包括break、continue、goto、return和throw语句。
l break语句用于终止最内层while、do、for和switch语句的执行。当程序遇到这一语句之后,执行紧接在被终止执行的语句后面的语句。
l using System;
l class BreakTest
l {
l public static void Main ()
l {
l for (int i = 1; i <= 100; i++)
l {
l if (i == 5)
l break;
l Console.WriteLine(i);
l }
l }
l } 运行结构 1 2 3 4
continue语句仅使最内层的循环体终止当前进行的这次循环。在while和do循环结构中,它将控制权转至对真值条件的计算。它与前面提到的break语句不同,它并不终止整个循环的执行,而仅仅终止当前这一次循环的运行。
l using System;
l class ContinueTest
l {
l public static void Main ()
l {
l for (int i = 1; i <= 10; i++)
l {
l if (i < 9)
l continue;
l Console.WriteLine(i);
l }
l }
l } 运行结果 9 10
goto语句也能用来跳出循环和switch语句。它无条件的转移程序的执行控制,其转移目的地是一个标号,因此要求标号与goto语句处在同一个函数中。
l using System;
l class testgoto
l {
l public static void Main ()
l {
l int x = 55;
l Console.WriteLine("x = {0}", x);
l if (x == 55)
l {
l x = 135;
l goto A; // Error
l }
l x = x + 1;
l A: for (int i=1; i<=5; i++)
l {
l Console.WriteLine(i);
l }
l Console.WriteLine("x = {0}", x);
l }
l }
x = 55
1
2
3
4
5
x = 135
l 析构函数在释放对象的时候被自动调用,可以在对象被删除前进行清理工作。在这里请与C#的垃圾回收机制进行比较,垃圾回收机制是自动进行清理工作,但并不是在对象被删除以前被触发的,只有程序处于一定的状态的时候才能发挥作用,所以应该养成显式的释放资源的好习惯。
l 析构函数为类名前有“~”号。其声明的方法如下:
l 属性可选 extern可选 ~ 标识符 ( ) 析构函数体
C# 编程指南
析构函数(C# 编程指南)
析构函数用于析构类的实例。
备注
· 一个类只能有一个析构函数。
· 无法继承或重载析构函数。
· 无法调用析构函数。它们是被自动调用的。
· 析构函数既没有修饰符,也没有参数。
例如,下面是类 Car 的析构函数的声明:
C# 复制代码 |
class Car { ~ Car() // destructor { // cleanup statements... } } |
该析构函数隐式地对对象的基类调用 Finalize。
对于您的应用程序创建的大多数对象,可以依靠 .NET Framework 的垃圾回收器隐式地执行所有必要的内存管理任务。但是,在您创建封装非托管资源的对象时,当您在应用程序中使用完这些非托管资源之后,您必须显式地释放它们。最常见的一类非托管资源就是包装操作系统资源的对象,例如文件、窗口或网络连接。虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理这些资源。对于这些类型的对象,.NET Framework 提供 Object.Finalize 方法,它允许对象在垃圾回收器回收该对象使用的内存时适当清理其非托管资源。默认情况下,Finalize 方法不执行任何操作。如果您要让垃圾回收器在回收对象的内存之前对对象执行清理操作,您必须在类中重写 Finalize 方法。
这样,前面的析构函数代码被隐式地转换为:
复制代码 |
protected override void Finalize() { try { // cleanup statements... } finally { base.Finalize(); } } |
这意味着对继承链中的所有实例递归地调用 Finalize 方法(从派生程度最大的到派生程度最小的)。
注意 |
不应使用空析构函数。如果类包含析构函数,Finalize 队列中则会创建一个项。调用析构函数时,将调用垃圾回收器来处理该队列。如果析构函数为空,则只会导致不必要的性能丢失。 |
程序员无法控制何时调用析构函数,因为这是由垃圾回收器决定的。垃圾回收器检查是否存在应用程序不再使用的对象。如果垃圾回收器认为某个对象符合析构,则调用析构函数(如果有)并回收用来存储此对象的内存。程序退出时也会调用析构函数。
可以通过调用 Collect 强制进行垃圾回收,但大多数情况下应避免这样做,因为这样会导致性能问题。有关更多信息,请参见强制垃圾回收。
使用析构函数释放资源
通常,与运行时不进行垃圾回收的编程语言相比,C# 无需太多的内存管理。这是因为 .NET Framework 垃圾回收器会隐式地管理对象的内存分配和释放。但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。当对象符合析构时,垃圾回收器将运行对象的 Finalize 方法。
资源的显式释放
如果您的应用程序在使用昂贵的外部资源,则还建议您提供一种在垃圾回收器释放对象前显式地释放资源的方式。可通过实现来自 IDisposable 接口的 Dispose 方法来完成这一点,该方法为对象执行必要的清理。这样可大大提高应用程序的性能。即使有这种对资源的显式控制,析构函数也是一种保护措施,可用来在对 Dispose 方法的调用失败时清理资源。
有关清理资源的更多详细信息,请参见下列主题:
· 清理非托管资源
示例
下面的示例创建三个类,这三个类构成了一个继承链。类 First 是基类,Second 是从 First 派生的,而 Third 是从 Second 派生的。这三个类都有析构函数。在 Main() 中,创建了派生程度最大的类的实例。注意:程序运行时,这三个类的析构函数将自动被调用,并且是按照从派生程度最大的到派生程度最小的次序调用。
C# 复制代码 |
class First { ~First() { System.Console.WriteLine("First's destructor is called"); } }
class Second: First { ~Second() { System.Console.WriteLine("Second's destructor is called"); } }
class Third: Second { ~Third() { System.Console.WriteLine("Third's destructor is called"); } }
class TestDestructors { static void Main () { Third t = new Third(); } } |
输出
Second's destructor is called
First's destructor is called