现在的位置: 首页 > 综合 > 正文

C#中的代理(Delegate)

2013年05月02日 ⁄ 综合 ⁄ 共 4075字 ⁄ 字号 评论关闭

    在学习多线程的过程中,又遇到了一个问题:C#代理.上网查了些资料,对代理有了一个初步的认识,记一点笔记.

    C#代理实际上类似于C++中的函数指针,因为C#中不存在指针,所以用代理可以完成一些原来在C++中用函数指针完成的操作,例如传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数指针不具备的优点。首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。 

    实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate: 
1. 声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。 
    声明一个代理的例子:
    public delegate int MyDelegate(string message);

2. 创建delegate对象,并将你想要传递的函数作为参数传入。 
     创建代理对象的方法:
    1). MyDelegate myDelegate = new MyDelegate(实例名.方法名);
    2). MyDelegate myDelegate = new MyDelegate(类名.方法名);
注:如果需要代理的方法是一个static静态方法的话,采用第2种方式,否则采用第1种方式。

3. 在要实现异步调用的地方,通过上一步创建的对象来调用方法。 
    可以直接使用代理调用代理所指向的方法:
    myDelegate(向方法传递的参数);

    下面是一些需要注意的事情:
“代理”(delegate)(代表、委托):“代理”是类型安全的并且完全面向对象的。
1)在C#中,所有的代理都是从System.Delegate类派生的(delegateSystem.Delegate的别名)。
2)代理隐含具有sealed属性,即不能用来派生新的类型。
3)代理最大的作用就是为类的事件绑定事件处理程序。
4)在通过代理调用函数前,必须先检查代理是否为空(null),若非空,才能调用函数。(5)在代理实例中可以封装静态的方法也可以封装实例方法。
6)在创建代理实例时,需要传递将要映射的方法或其他代理实例以指明代理将要封装的函数原型(.NET中称为方法签名:signature)。注意,如果映射的是静态方法,传递的参数应该是类名.方法名,如果映射的是实例方法,传递的参数应该是实例名.方法名。
7)只有当两个代理实例所映射的方法以及该方法所属的对象都相同时,才认为它们是想等的(从函数地址考虑)。
8)多个代理实例可以形成一个代理链,System.Delegate中定义了用来维护代理链的静态方法CombionRemove,分别向代理链中添加代理实例和删除代理实例。
9)代理的定义必须放在任何类的外面,如delegate int MyDelegate();而在类的方法中调用MyDelegate d = new MyDelegate(MyClass.MyMethod);来实例化自定义代理的实例。
10)代理三步曲:
a.生成自定义代理类:delegate int MyDelegate();
b.然后实例化代理类:MyDelegate d = new MyDelegate(MyClass.MyMethod);
c.最后通过实例对象调用方法:int ret = d();
 

    

分类: .NET
1
0
(请您对文章做出评价)
« 博主前一篇:[ZT]C#的多线程机制探索(4)
» 博主后一篇:C#中的文件操作
 posted on 2005-08-28
14:33
 寒带鱼 阅读(8580) 评论(7编辑 收藏

 斧头帮少帮主   | 2006-12-06
17:40
简单明了实用. 
本类我想写下,看到你的帖子,我就没信心了. 
 爱不留[未注册用户] | 2007-04-08
19:56
呵呵.
(9)代理的定义必须放在任何类的外面,

这句不尽然. 代理实际上可以定义在一个类内.
有机会讨论.QQ:334545190

 柿子也疯狂[未注册用户] | 2007-05-14
19:54
恩。写的不错。。有参考价值。。。谢谢。。
 Lang_Hai   | 2007-05-21
23:40
我还是有点模糊,能有个例子说明一下吗?(说明代理有什么用及怎么用) 
谢谢了。。
 CDplayer   | 2007-08-21
20:51
 chinaifne   | 2007-11-02
12:39
同意#2楼的说法,可以写在类内的。 
我放上来一个例子 
using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication1 

//delegate string strDelegate(string str); 

class Program 

delegate string strDelegate(string str); 

static string strReplace(string s) 

return s.Replace(' ', '_'); 

static string strRemove(string s) 

string temp=""; 

for (int i = 0; i < s.Length; i++) 

if (s[i]!=' ') 

temp += s[i]; 

return temp; 

static string strReverse(string s) 

int i, j; 
string temp=""; 

for (i = 0; i < temp.Length; i++) 

return temp; 

static void Main(string[] args) 

strDelegate strD; 
string str; 

strD= new strDelegate(strRemove); 
str = strD("asfa asdf asdf asdf asdf"); 
Console.WriteLine(str); 

strD = new strDelegate(strReplace); 
str = strD("asdf asdf"); 
Console.Out.WriteLine(str); 



这里代理放在类内和类外都一样的!!

 虚拟世界男孩   | 2009-12-27
17:06
你的说法有错误哦,虽然没细看,,但 C#中 确实 有指针哦,只是 她是 unsafe的!!!
其他写的笔记的还行!

using System;
using System.Collections.Generic;
using System.Text;

namespace MystrDelegate
{
    delegate string MystrDelegate(string str);

    class Program
    {
        //delegate string strDelegate(string str);  

        static string strReplace(string s)
        {
            return s.Replace(' ', '_');
        }

        static string strRemove(string s)
        {
            /* 
            string temp = ""; 
 
            for (int i = 0; i < s.Length; i++) 
            { 
                if (s[i] != ' ') 
                { 
                    temp += s[i]; 
                } 
            } 
 
            return temp; 
             */
            StringBuilder sb = new StringBuilder(s.Length);
            for (int i = 0; i < s.Length; i++)
            {
                if (s[i] != ' ')
                {
                    sb.Append(s[i]);
                }
            }

            return sb.ToString();
        }

        static string strReverse(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                throw new ArgumentException("参数不合法");
            }

            StringBuilder sb = new StringBuilder(str.Length);
            for (int index = str.Length - 1; index >= 0; index--)
            {
                sb.Append(str[index]);
            }
            return sb.ToString();
        }

        static void Main(string[] args)
        {
            MystrDelegate strD;
            string str;

            strD = new MystrDelegate(strRemove);
            str = strD("asfa asdf asdf asdf asdf");
            Console.WriteLine(str);

            strD = new MystrDelegate(strReplace);
            str = strD("asdf asdf");
            Console.Out.WriteLine(str);

            strD = new MystrDelegate(strReverse);
            str = strD("asdf");
            Console.Out.WriteLine(str);
        }
    }
}
/*
 asfaasdfasdfasdfasdf
asdf_asdf
fdsa
请按任意键继续. . .
 */

抱歉!评论已关闭.