浅析C#中的托付

托付是寻址方法的.NET版本号。在C++中。函数指针仅仅只是是一个指向内存位置的指针,它不是类型安全的。而.NET托付全然不同,托付是安全类型的类,它定义了返回类型和參数的类型。

当把方法传递给其它方法时,须要使用托付。

C#中使用一个类时,分两个阶段。

首先须要定义这个类,即告诉编译器这个类由什么组成的。然后,实例化一个对象(除非仅仅使用静态方法)。

对于托付也是相似,也须要两个步骤。

首先必须定义要使用的托付。然后必须创建该托付的一个或多个实例。

定义语法:

delegate void IntMethodInoker(int x);
delegate double TwoLongsOp(long first, long second);
delegate string GetString();

定义托付基本上是定义一个新类。所以能够在定义类的不论什么同样地方定义托付。即能够在还有一个类的内部定义,能够在不论什么类的外部定义,能够在名称空间中把托付定义为顶层对象。

依据托付定义的可见性,和托付的作用域,能够在托付的定义上应用随意常见的訪问修饰符:public、private、protected等

比如:

public delegate string GetAString();

使用托付:

private delegate string GetAString();
static void Main()
{
    int x=40;
    GetAString firstStringMethod = new GetAString(x.ToString);
    Console.WriteLine("String is {0}",firstStringMethod () );
}

由上述代码能够看到。C#的托付在语法上总是接受一个參数的构造函数。这个參数就是托付引用的方法,可是这种方法必须匹配最初定义托付时的签名。

实际上。给托付实例提供圆括号与调用托付类的Invoke()方法全然同样。

使用Invoke完毕一个托付方法的封送。就相似于使用SendMessage方法来给界面线程发送消息,是一个同步方法。也就是说在Invoke封送的方法被运行完毕前,Invoke方法不会返回,从而调用者线程将被堵塞。

由于firstStringMethod 是一个托付类型的变量,所以C#编译器会用firstStringMethod.Invoke()取代firstStringMethod ()。

firstStringMethod();
firstStringMethod.Invoke();

为了降低输入量。仅仅须要托付实例,就能够仅仅传递地址的名称,即托付判断

GetAString firstStringMethod = new GetAString(x.ToString);
GetAString firstStringMethod = x.ToString;

注意:输入行事不能是x.ToString()。也不能把它传给托付变量。x.ToString表示把方法的地址赋予托付变量。

多播托付:

托付能够包括多个方法,这样的托付称为多播托付。假设调用多播托付。就能够按顺序连续调用多个方法。可是,托付的签名必须返回void。否则仅仅能得到托付调用的最后一个方法的结果。

多播托付演示样例程:

delegate void Delegate_Multicast(int x, int y);
Class Class2
{
    static void Method1(int x, int y)
    {
      Console.WriteLine("You r in Method 1");
    }
    static void Method2(int x, int y)
    {
      Console.WriteLine("You r in Method 2");
    }
    public static void Main()
    {
      Delegate_Multicast func = new Delegate_Multicast(Method1);
      func += new Delegate_Multicast(Method2);
      func(1,2);             // Method1 and Method2 are called
      func -= new Delegate_Multicast(Method1);
      func(2,3);             // Only Method2 is called
   }
}    

解析:

上面的演示样例程序分别定义了名为method1 和 method2的两个接受整型參数、返回类型为void的方法。

在Main函数里使用以下的声明创建托付对象:

Delegate_Multicast func = new Delegate_Multicast(Method1);

然后使用+= 来加入托付,使用-=来移除托付。

合并托付:

托付对象的一个用途在于,能够使用 + 运算符将它们分配给一个要成为多路广播托付的托付实例。

组合的托付可调用组成它的那两个托付。

仅仅有同样类型的托付才干够组合。

- 运算符可用来从组合的托付移除组件托付。

delegate void Del(string s);

class TestClass
{
    static void Hello(string s)
    {
        System.Console.WriteLine("  Hello, {0}!", s);
    }

    static void Goodbye(string s)
    {
        System.Console.WriteLine("  Goodbye, {0}!", s);
    }

    static void Main()
    {
        Del a, b, c, d;

        // Create the delegate object a that references
        // the method Hello:
        a = Hello;

        // Create the delegate object b that references
        // the method Goodbye:
        b = Goodbye;

        // The two delegates, a and b, are composed to form c:
        c = a + b;

        // Remove a from the composed delegate, leaving d,
        // which calls only the method Goodbye:
        d = c - a;

        System.Console.WriteLine("Invoking delegate a:");
        a("A");
        System.Console.WriteLine("Invoking delegate b:");
        b("B");
        System.Console.WriteLine("Invoking delegate c:");
        c("C");
        System.Console.WriteLine("Invoking delegate d:");
        d("D");
    }
}

/*-------------------------
输出
Invoking delegate a:
  Hello, A!
Invoking delegate b:
  Goodbye, B!
Invoking delegate c:
  Hello, C!
  Goodbye, C!
Invoking delegate d:
  Goodbye, D!
  ----------------------*/

匿名方法:

到眼下为止。要想使用托付工作。方法必须已经存在。可是还有还有一种使用托付的方法:即通过匿名方法。

匿名方法是用作托付的參数的一段代码。

用匿名方法定义托付的语法与前面的定义并没有差别。

但在实例化的时候就有了差别了。

假设使用匿名方法。则不必创建单独的方法,因此降低了实例化托付所需的编码系统开销。

比如。假设创建方法所需的系统开销是不必要的,在托付的位置指定代码块就非常实用。启动新线程即是一个非常好的演示样例。无需为托付创建很多其它方法,线程类就可以创建一个线程而且包括该线程运行的代码。

void StartThread()
{
    System.Threading.Thread t1 = new System.Threading.Thread
      (delegate()
            {
                System.Console.Write("Hello, ");
                System.Console.WriteLine("World!");
            });
    t1.Start();
}

托付类型派生自 .NET Framework 中的 Delegate 类。

托付类型是封装的,它们不能派生出其它类,也不能从 Delegate 派生出自己定义类。 由于实例化的托付是一个对象。因此能够作为參数传递或分配给一个属性。 这同意方法作为參数接受托付并在稍后调用托付。

这被称为异步回调,是在长进程完毕时通知调用方的经常用法。 当以这样的方式使用托付时。使用托付的代码不须要知道要使用的实现方法。 功能相似于封装接口提供的功能。

时间: 2024-10-28 07:35:51

浅析C#中的托付的相关文章

浅析python中_name_='_main_'

刚接触到python时,对代码中的_name_='_main_'比较疑惑,本文对其的讲解借鉴了其他博客讲述(见参考资料),希望和大家共同学习. Make a script both importable and executable 首先先看一个例子 1 #module.py 2 def main(): 3 print "we are in %s"%__name__ 4 if __name__ == '__main__': 5 main() 在这段函数中,定义main函数,当py文件被

浅析python 中__name__ = '__main__' 的作用

很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码,可能很多新手一开始学习的时候都比较疑惑,python 中__name__ = '__main__' 的作用,到底干嘛的? 有句话经典的概括了这段代码的意义: "Make a script both importable and executable" 意思就是说让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行. __name__ 是当前模块名,当模块

从源码中浅析Android中如何利用attrs和styles定义控件

一直有个问题就是,Android中是如何通过布局文件,就能实现控件效果的不同呢?比如在布局文件中,我设置了一个TextView,给它设置了textColor,它就能够改变这个TextView的文本的颜色.这是如何做到的呢?我们分3个部分来看这个问题1.attrs.xml  2.styles.xml  3.看组件的源码. 1.attrs.xml: 我们知道Android的源码中有attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性 你可以找到attr

浅析Java中的final关键字(转)

浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下面是本文的目录大纲: 一.final关键字的基本用法 二.深入理解final关键字 若有不正之处,请多多谅解并欢迎指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin0520/p/3736238.html 一

浅析Java中的访问权限控制

浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但是工程师A并不希望ClassA被该应用中其他所用的类都访问到,那么该如何处理? 场景2:如果工程师A编写了一个类ClassA,其中有两个方法fun1.fun2,工程师只想让fun1对外可见,也就是说,如果别的工程师来调用ClassA,只可以调用方法fun1,那么该怎么处理? 此时,访问权限控制便可以

浅析C#中抽象类和接口的区别

文章<浅析C#中接口的重要性>中讲述了如何声明和使用接口. 但是C#具有abstract关键字形成的抽象类,那么二者我们该如何选择呢! C#允许把类和函数声明为abstract.抽象类不能实例化,而抽象函数也不能直接实现,必须在非抽象的派生类中重写.显然,抽象函数本身是虚拟的,但是不能提供virtual关键字.如果类包含了抽象函数,则该类也是抽象的,必须声明为抽象. 定义抽象类: public abstract class Animal { protected string _name; pu

再看C#中的托付和事件

在一口一个设计模式--观察者模式中.我们已经知道怎样应用观察者模式,但通过近期的深入学习,发现观察者模式存在下面缺陷: 1.抽象通知者依赖于抽象观察者: 2.每一个详细观察者被调用的方法必须一致. 比方在机房收费系统中关于观察者模式的应用例如以下图所看到的: 这个设计存在下面问题: 1.抽象通知者须要把抽象观察者中的全部详细对象加入到集合中,以备向每一个详细观察者发送通知消息. 2.在发送通知消息时.详细观察者中被通知的方法必须一致,否则详细通知者无法完毕遍历: 3.更新卡内剩余金额.更新学生上

浅析 JavaScript 中的 函数 currying 柯里化

原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果.因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程. 柯里化一个求和函数 按照分步求值,我们看一个

浅析python中的类变量和对象变量

刚学python,学到了有关于类和对象的地方.对一个概念有点模糊,后来通过实践编码找到一定规律 在python中 class test(object): id=2 name='tt' list=['tt','dd'] def change(self,newA,new_id): self.id=new_id self.age=newA return self.age t1 = test() t1.change(21, 3) print t1.id #3 t2 = test() t2.age = 2