C# 委托基础

不知不觉,又开始委托的学习了,感觉这个东西我能学一辈子,哈哈哈!这次看的是官方的参考书(C#高编9),每次看不同的资料,总能学到不同的知识!言归正传

1、为什么要使用委托?

我们习惯于将数据作为参数传递给方法,但是很多时候我们需要将一个方法传递给另一个方法。所以委托就是干这个的,将方法作为参数,传递给另一方法.

举个例子:在C#中,可以告诉计算机并行执行某些新的执行序列,同时运行当前任务,这个序列就称之为线程,如果要告诉计算机启动一个新的线程,就必须告诉线程入口方法在哪里,并告诉计算机开始启动方法的细节,所以线程(Thread)的构造函数必须带有一个参数,该参数定义了线程调用的方法。这里就使用到了委托的概念,将方法传递给线程!

2、委托的特性

在C和C++中,只能提取函数的地址,该地址可以作为参数传递给任何需要它的函数,这种方法会导致类型安全问题。但是在.Net Framework中,当我们进行面向对象编程的时候,几乎没有方法是孤立存在的,当我们吊用一个方法前,必须确保这个方法与类实例关联,所以在.Net Framework中不允许直接使用方法,或者传递方法,如果需要传递方法,那么必须把该方法的细节和参数封装在一个类对象中,通过传递对象实例的方式,来传递方法。但是用类对象来传递方法,有点大材小用了,所以.Net Framework中定义了一种新的类型对象-委托,这种对象专门用来传递方法,如果我们要传递一个方法,就必须把方法的细节封装到委托中。通过委托实例来传递方法,所以委托和类其实在某种程度上说是一样的,委托是一种特殊的类。这种类,专门负责传递方法。

3、声明委托

2中,提到了委托其实是一种特殊的类,所以它的申明方式和类其实是差不多的,只不过类用class来修饰,且类有方法体,而委托使用delegate来修饰没有方法体,委托必须声明委托所代表的一类方法的返回值,并且声明这类方法的参数,代码如下:

public delegate void MyDeleagte(int a);

一个无返回值,带一个int参数的委托申明好了。

如果要定一个委托,不带参数,返回一个string类型的值,代码如下:

public delegate string MyDelegate();

4、委托的结构

当我们定义完一个委托,实际上是定义了一个类,委托实现为派生自System.MulticastDelegate抽象类的类,System.MulticastDelegate又派生字System.Delegate,C#编译器能识别这个类,会使用其委托语法.

5、委托中注册的方法的使用

委托中方法的调用有两种方式:

a、委托变量加括号的方式,代码如下:

public delegate void GetString();
    class Program
    {
        static void Main(string[] args)
        {
            var a = new GetString(aa);
            a += aa;
            a += aa;
            a += aa;
            a += aa;
            a += aa;
            a();
            Console.ReadLine();
        }
        static void aa()
        {
            Console.WriteLine("1");
        }
    }

b、使用Invoke()方法

    public delegate void GetString();
    class Program
    {
        static void Main(string[] args)
        {
            var a = new GetString(aa);
            a += aa;
            a += aa;
            a += aa;
            a += aa;
            a += aa;
            a.Invoke();
            Console.ReadLine();
        }
        static void aa()
        {
            Console.WriteLine("1");
        }
    }

上面是最常规的委托使用方法,当然还有其他的如:BeginInvoke()等,这里不做解释,如想要了解,请参考C# 委托进阶

6、多播委托

上面的实例中,我给一个委托绑定了多个方法,如果要多次调用这些方法,就需要显示多次吊用。我们把一个委托,如果这个委托绑定了多个方法,称为多播委托,如果调用多播委托,就可以按顺序连续吊用多个方法。为此,委托的签名必须返回void,否则就只能得到最后一个方法的返回值。

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> options = new Action<double>(MutiplyByTwo);
            options += Square;
            options.Invoke(3);
            Console.ReadLine();
        }
        static void MutiplyByTwo(double a)
        {
            Console.WriteLine("Mutiplying by 2:{0} gives {1}", a, a * 2);
        }
        static void Square(double a)
        {
            Console.WriteLine("Squareing :{0} gives {1}", a, a * a);
        }
    }

上面是最基本的使用多播委托的方法,但是它存在以下问题

a、对同一个委托调用方法链的顺序并未正式定义,因此应避免编写依赖于特定顺序的调用方法的代码。

b、通过一个委托调用多个方法还可能导致大问题,当一个方法抛出异常,整个迭代就会停止

b的实现代码如下:

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> options = new Action<double>(MutiplyByTwo);
            options += Square;
            options.Invoke(3);
            Console.ReadLine();
        }
        static void MutiplyByTwo(double a)
        {
            Console.WriteLine("Mutiplying by 2:{0} gives {1}", a, a * 2);
            throw new Exception("我出异常啦");
        }
        static void Square(double a)
        {
            Console.WriteLine("Squareing :{0} gives {1}", a, a * a);
        }
    }

第二行代码并没有正常输出,ok,那么将异常捕获,看它会不会执行第二行代码,代码如下:

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> options = new Action<double>(MutiplyByTwo);
            options += Square;
            try
            {
                options.Invoke(3);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception Caught");
            }
            Console.ReadLine();
        }
        static void MutiplyByTwo(double a)
        {
            Console.WriteLine("Mutiplying by 2:{0} gives {1}", a, a * 2);
            throw new Exception("我出异常啦");
        }
        static void Square(double a)
        {
            Console.WriteLine("Squareing :{0} gives {1}", a, a * a);
        }
    }

异常被捕获,但是第二行代码还是没有执行,这是因为第一个方法抛出了异常,所以委托的迭代会停止,不再调用下面的方法。

b的解决方法:

为了解决上面的问题,Delegate类定义了GetInvocationList方法,他返回一个Delegate[]数组。现在可以使用对象吊用委托对应的方法,捕获异常,并进行下一次迭代,代码如下:

class Program
    {
        static void Main(string[] args)
        {
            Action<double> options = new Action<double>(MutiplyByTwo);
            options += Square;
            Delegate[] delegates = options.GetInvocationList();
            foreach (Action<double> a in delegates)
            {
                try
                {
                    a.Invoke(3);
                }
                catch (Exception)
                {
                    Console.WriteLine("Exception Caught");
                }
            }
            Console.ReadLine();
        }
        static void MutiplyByTwo(double a)
        {
            Console.WriteLine("Mutiplying by 2:{0} gives {1}", a, a * 2);
            throw new Exception("我出异常啦");
        }
        static void Square(double a)
        {
            Console.WriteLine("Squareing :{0} gives {1}", a, a * a);
        }
    }

ok,问题解决,异常顺利的捕获,且委托的迭代正常完成!

时间: 2024-10-02 23:54:42

C# 委托基础的相关文章

C#委托——基础2

在上一篇随笔中,简要说明了怎样定义委托,定义事件,订阅事件,最后也实现了效果,就是当员工类的某个对象,执行某个事件时,委托事件被触发,后面也得到了结果,但是想象一下实际场景中,如果办公室有员工玩游戏了,这个时候,我们要找到是谁,在哪个位置玩游戏,而不是向所有人广播有人玩游戏了,这样并没有什么意义.因此,需要对上篇的代码进行改进,所以就要想办法传递参数,参数中需要包含必要的信息. 在本例中,关于参数,首先创建了一个参数类, CustomeEvebtArgs 且继承自EventArgs(这个我看的例

C#委托——基础1

在面向对象的高级语言中,委托具有广泛的使用领域,当然在C#中,委托的使用方式与使用逻辑与其他编程语言相比大同小异,这里通过自学关于C#中委托的内容简略谈谈委托的使用语法与使用逻辑. 任何技术都是因需求而产生的,这里通过一个例子简单阐述委托需求的参数,以及在实现一个委托时,委托的定义,事件的定义,事件的订阅,传递参数,多播委托.首先说说委托需求的产生(在许多情况下都需要运用委托,书面上的定义不是显得太容易理解,这里以一幅图为例). 可以将委托简单理解为上图所示,当员工做了某件事件时,这个时候,我们

C# 委托---基础

委托是一个类可以把一个方法当作另一个方法的参数使用. 声明委托:delegate string 委托名(参数列表);使用委托的函数 返回值和参数列表与委托相同使用委托: 委托名 委托变量名=new 委托(函数名); 委托变量名(参数列表); 例子: delegate string de1(string name,int age);//定义 static string CN(string name, int age) { return name + " 的年龄是 " + age; } s

委托基础详解

/*委托是一个类型安全的对象        * 它指向程序中另一个以后被调用的方法或多个方法.委托类型包含3个重要的信息:        * 1:它所调用的方法的名称        * 2:该方法的参数(可选)        * 3:该方法的返回值(可选)        * 注:.net委托既可以指向静态方法,也可以指向实例方法        *         * 当一个委托对象被创建并提供了上述信息后,它可以在运行时动态调用其他指向的方法,可以看到 .Net Framework 中每个委托(

.NET基础拾遗(4)委托、事件、反射与特性

Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 一.委托基础 1.1 简述委托的基本原理 委托这个概念对C++程序员来说并不陌生,因为它和C++中的函数指针非常类似,很多码农也喜欢称委托为安全的函数指针.无论这一说法是否正确,委托的的确确实现了和函数指针类似的功能,那就是提供了程序回调指定方法的机制. 在委托内部,包含了一个指向某个方法的指针(这一点上委托实现机制和C++的函数指针一致),为何称其

有关委托的理解

一.委托 (一).委托基础: 1.       先看看代码: (1).定一个方法:void SayHi(string name){Console.WriteLine(“Hi~”+name+”! ” );} (2).声明一种委托类型:delegate void DGSayHi(string uName); (3).创建委托类型对象:DGSayHi dgObj = new DGSayHi(SayHi);//构造函数中传入了方法 (4).执行委托:dgObj(“IT狂人”); //调用委托(奇怪:对象

委托知识整理笔记

委托知识整理笔记 一.委托基础 1.1   委托是什么 与类.枚举.结构.接口一样,委托也是一种类型.类是对对象的抽象,委托是对函数的抽象.一个委托代表了具有相同参数列表和返回值的(具有相同签名(signature))所有函数. 1.2   为什么要使用委托?能给我带来哪些好处? 有时在程序设计时,某個方法在执行时可能需要根据不同情形做不同处理并且这些情形根据时间可能还会有变动,所以这部分代码没法写死.所以C#就设计了委托来处理这些情形,将这些变化不定的细节交由委托来处理,委托来代理多个类似的处

异步委托

委托实现多窗体传值 主窗体的代码: public partial class FrmMain : Form { //[3] 创建委托对象(委托对象能够将委托和具体方法关联) public ShowCounterDelegate msgSender; public FrmMain() { InitializeComponent(); //创建从窗体对象 FrmOther01 objFrm01 = new FrmOther01(); FrmOther02 objFrm02 = new FrmOthe

C# 委托应用总结

一.什么是委托 委托基础拓展:http://www.cnblogs.com/yangyancheng/archive/2011/04/21/2024145.html 1.1官方解释 委托是一种定义方法签名的类型.当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法. 1.2个人理解 委托就是执行方法(函数)的一个类. 事件是一种特殊的委托. 二.如何申明委托 2.1 delegate public delegate int TestDelegate(int x