C#之语言详述

	上一篇写到的是C#的核心语言,属于泛泛而谈。这一篇继续C#的学习,开始对C#语言的详述,本篇内容主要包括委托、事件和异常处理。
一. 委托
	要理解委托的概念,必须清楚什么是函数指针。
	函数指针是对函数的间接引用,支持通过变量来调用函数。通过函数指针,我们可以将函数作为一个参数或作为一个返回值进行传递。函数指针可以使应用程序更灵活、可扩展性和可伸缩性更好。但函数指针不是类型安全的。
	从生活角度去理解,我觉得函数指针就像是一个快递点。在这里,当我们需要的时候,我们可以通过它来取件寄件。
	一个“委托”是对一个或多个函数指针的一种抽象。委托是一个引用类型,具有一个签名和返回类型。事件是最实用的委托应用程序之一。事件在后面还会有详细阐述。
	下面是对委托的一般过程进行了解:一般包括定义、创建和调用这三个步骤。
	(1)delegate关键字是用于定义新委托的。以下代码定义了一个新的委托,名为DelegateClass的类:
一个委托可以在命名空间中、在类中进行定义,但不能在一个方法中作为一个类字段或一个局部变量进行定义。
public delegate int DelegateClass(string info); //定义一个委托


(2)new关键字是用于为一个委托创建一个实例。委托的构造函数不能被重载。这里包含三种不同的情况,以下代码是对类进行初始化的三种情况:

a) 对于一个实例方法,采用object.method格式

b) 对于一个静态方法,采取class.method格式

c) 对于方法和委托包含在同一类中,则既不需要对象名,也不需要类名。
public delegate void DelegateClass();
public class constructors
        {
            public static void Main()
            {
                DelegateClass del1 = new DelegateClass(constructors.MethodA);
                //静态方法下的实例化
                DelegateClass del2 = new DelegateClass(MethodA);
                //指定的方法和委托包含在同一类中下的实例化
                ZClass obj = new ZClass();
                DelegateClass del3 = new DelegateClass(obj.MethodB);
                //实例方法下的实例化
            }
            public static void MethodA()
            {
            }
        }
        public class ZClass
        {
            public  void  MethodB()
            {
            }
        }

	(3)invoke方法对委托进行调用。如果委托包含一个函数指针,函数的返回就成为委托的返回。当多个函数指针被存储到指定委托的时候,最后一个函数的返回就成为委托的返回。
二.事件
	在学习VB的时候,就了解到的一句话是:以事件驱动程序。在编程时,我们也是想要实现某项功能,就在相应的事件下去编写代码。比如:点击“登录”按钮,就进入到机房收费系统的主界面。我们就可以在Command按钮下的Click事件下编写代码,从而驱动程序。
	在这本书C#中写道,一个事件是指一个对象或类想要通知其他人有事发生(这里指的其他人是另一个类,而不是另一个对象)。这就是在加入面向对象思想后的一个变化,所有的一切都是在类中打交道。
	任何对一个事件感兴趣的对象或类都可以订阅该事件。订阅者通过提交一个委托为一个事件进行注册。该委托必须是单角色的,并且只包含一个单独的函数指针,这个函数是订阅者对该事件的响应。当指定的事件被引发的时候,发布者调用该函数,给订阅者提供一个对事件进行响应的机会。该函数被称为一个事件处理程序。事件可以有多个订阅者,而没有订阅者的事件不会被引发。
	上面说了很多专业的语言,我觉得简单理解来看,其实就是一个事件可以被多次访问,从而做出相应的处理程序;也可以是无人访问,不过这样的事件就是不会被引发罢了。
	(1)event关键字用于定义一个事件
<pre name="code" class="csharp">accessibility event delegatename eventname
	(2)public或protected关键字一般是对一个事件的可访问性设置
public delegate void DelegateClass();
<pre name="code" class="csharp">public event DelegateClass MyEvent;

	(3)add和remove方法用于订阅和取消订阅
	(4)引发事件是用调用运算符“()”,添加调用运算符到事件就会引发该事件。
public void SomeMethod()
{
      if (anEvent!=null)
      {
          anEvent(null,null);
      }
}
三.异常处理

什么是异常?异常是应用程序发生异常事件或错误情况,分为系统异常和应用程序异常。

系统异常是公共语言运行时(CLR)引发的,包括空引用、内存泄漏、被零除和堆栈溢出异常。应用程序异常,被看做是自定义异常,是由应用程序引发的。

(1)异常举例

常见的一个异常就是被零除,也就是零被作为除数。如下面代码,发生了被零除异常,终止了程序。

public static void Main()
{
       int var1=5,var2=0;
       var1/=var2;//exception occurs
}

把可能产生异常的代码放在一个try块中,因为try块中的代码是受异常保护的,这样就可以捕获异常。catch块处理异常,显示堆栈跟踪。

public static void Main()
        {
            try
            {
                int var1 = 5, var2 = 0;
                var1 /= var2;//exception occurs
            }
            catch (DivideByZeroException except)
            {
                Console.WriteLine("Exception " + except.StackTrace);
            }
        }

这样运行结果就是会提醒程序具体哪一行出错:

(2)结构化的异常处理

也就是一个专门负责异常处理的工具名称。它通过评估堆栈决定何时代码受保护和何处捕捉和处理一个异常。

a)try语句:监视器,监视保护代码中的异常。

下面是一个在超过数组边界时发生的边界溢出处理错误。

public static void Main()
        {
            try
            {
                MethodA();
            }
            catch (Exception except)
            {
                Console.WriteLine( except.Message);
            }
        }
        public static void MethodA()
        {
            int[] values = { 1, 2, 3, 4 };
            for (int count = 0; count <= values.Length; ++count)
            {
                Console.WriteLine(values[count]);
            }
        }

结果是在未保护的MethodA方法中的一个异常,Main调用MethodA,Main的范围包括MethodA,因此,Main中的try块扩展保护到MethodA。异常在Main中被捕捉。

b)catch语句:筛选和处理异常。其中筛选器可以帮助我们捕捉各类异常。

catch筛选器是可选的,默认的是catch all。在(1)中,异常举例的DivideByZeroException就是专门捕捉被零除异常的。下面代码属于一个默认的:

public static void Main()
        {
            try
            {
                int var1 = 5, var2 = 0;
                var1 /= var2;
            }
            catch
            {
                //catch remaining managed and unmanaged exceptions
            }
        }

c)finally语句:终结处理器。起到一个可以关闭文件、释放一个数据库或其他的管理资源的用途。

下面是一个典型的终结处理器:

using System;
using System.IO;
namespace ConsoleApplication1
{
    public class FileWrite
    {
        public static void Main()
        {
            StreamWriter sw = null;
            try
            {
                sw = new StreamWriter("date.txt");
                sw.Write(DateTime.Now.ToLongTimeString());
                throw new ApplicationException("exception");
                //dangling code
            }
            finally
            {
                sw.Close();
                Console.WriteLine("file closed");
            }
        }
    }
}

d)语句使用规范

使用必须与一条catch或finally语句成对使用。可以有零到多条catch语句和一条try语句结合使用,没有或只有finally一条语句。如果catch和finally语句同时出现,则catch语句应在finally语句之前。

四.总结

这一编的学习把委托又重新认识了一遍,以前总觉得很难理解,现在觉得其实从生活中去看,委托无处不在。如何去定义,如何去调用,在不同的情况下如何正确去实例化,这都是在这一次中学习中的收获。对于try-catch-finally语句,也是在很早就编写过,看似比较简单,实际上也是内容丰富,现在的我们还都是在用调试阶段就可以应付,但以后就不一样了,异常的情况可能会经常碰到,所以这也是一个很基础的学习。

在期末复习阶段,学了些C#的东西,后天就要开学了,机房重构,就要真正开始了。Come On!

				
时间: 2024-08-18 20:41:06

C#之语言详述的相关文章

详述三种现代JVM语言--Groovy,Scala和Clojure

Java的遗产将是平台,而不是程序设计语言. Java技术的原始工程师们作出了一个明智的决定,就是将编程语言与运行时环境分开,最终这使得超过200种语言能够运行在Java平台上.这种架构对于该平台的长期活力是至关重要的,因为计算机程序设计语言的寿命一般都是比较短.从2008年开始,由Oracle主办的一年一度的JVM语言峰会为JVM上其它的语言实现与Java平台工程师进行开放式合作提供了机遇. 欢迎来到Java.next专栏系列,在本系列的文章中,我将讲述三种现代JVM语言--Groovy,Sc

[转载] 详述三种现代JVM语言--Groovy,Scala和Clojure

转载自http://www.tuicool.com/articles/jYzuAv和http://www.importnew.com/1537.html 在我与Martin Fowler曾经合作呈现的一次主题演讲中,他作出了一个有洞察性的观点: Java的遗产将是平台,而不是程序设计语言. Java技术的原始工程师们作出了一个明智的决定,就是将编程语言与运行时环境分开,最终这使得超过200种语言能够运行在Java平台上.这种架构对于该平台的长期活力是至关重要的,因为计算机程序设计语言的寿命一般都

UML(Unified Modeling Language)统一建模语言

什么是模型 模型是对现实的简化 模型是提供系统的蓝图,模型可是包括详细计划.也可是是从更高程度考虑系统的总体计划,每个系统可以从不同的方面用不通过的模型来描述.因而每个模型都是在语义上闭合的抽象系统.模型可以是结构性的,强调系统的组织.也可是是行为性的,强调系统的动态方面 举例:售楼中心里面的楼盘蓝图 为什么建模 建模是为了能够更好地理解正在开发的系统 通过建模达到下面的目的1.模型有助于按照实际情况或按照所需的样式对系统进行可视化2.模型能够规约系统的结构或行为3.模型给出了构造系统的模板4.

Javascript教程:js异步编程的4种方法详述(转载)

文章收集转载于(阮一峰的网络日志) 你可能知道,Javascript语言的执行环境是“单线程”(single thread). 所谓“单线程”,就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推. 这种模式的好处是实现起来比较简单,执行环境相对单纯:坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方

[R语言]关联规则2---考虑items之间严格的时序关系

前面介绍了关联规则1---不考虑用户购买的items之间的时序关系,但在一些情况下用户购买item是有严格的次序关系了,比如在某些休闲游戏中,用户购买了道具A才能购买道具B,且道具A和B只能购买一次,也就是说购买了道具A是购买道具B的充分条件,如果购买道具A的用户通常会购买道具A,在不考虑时序关系的时候,会得出“BàA”这样的关联规则,这会给运营的同事这样的结论:“购买了道具B的用户也非常有可能会购买道具A,当用户购买了道具B时应向其推荐道具A”,这从数据角度来说是没有问题的,但是从业务的角度来

C 语言中的指针和内存泄漏

引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具. 本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密.本文内容包括: 导致内存破坏的指针操作类型 在使用动态内存分配时必须考虑的检查点 导致内存泄漏的场景 如果您预先知道什么地方可能出错,那么您就能够小

【转】C 语言中的指针和内存泄漏

避免陷阱 级别: 中级 Manish Virmani ([email protected]), 高级软件工程师, IBM 2006 年 10 月 26 日 在使用 C 语言时,您是否对花时间调试指针和内存泄漏问题感到厌倦?如果是这样,那么本文就适合您.您将了解可能导致内存破坏的指针操作类型,您还将研究一些场景,了解要在使用动态内存分配时考虑什么问题. 引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试

R语言应用

文章参考  << R 数据分析  -- 方法与案例详解  >> R的官方网站是http://www.r-project.org, 在R官方主页点击download  R,然后选择对应的镜像后,在右侧下载和安装包栏目里会 出现三种操作系统的R版本(Linux.(Mac)  OS  X.Windows),选择点击相应的操作系 统后,再选择点击base就会进入R的下载页面,在页面上会出现R的最新版本和安装说明等 不过,要使用RStudio,除了安装R开发环境后,还需要到 htt

WPF学习------XAML 语法详述

XAML 语言规范 XAML 语言规范中也定义或引用了此处定义的 XAML 语法术语. XAML 是一种基于 XML 并遵循或扩展 XML 结构规则的语言. 其中某些术语共享自或基于描述 XML 语言或 XML 文档对象模型时常用的术语. 有关 XAML 语言规范的更多信息,请从 Microsoft 下载中心下载 [MS-XAML]. XAML 和 CLR XAML 是一种标记语言. 顾名思义,公共语言运行时 (CLR) 实现了运行时执行. XAML 本身并非 CLR 运行时直接使用的一种公共语