首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

何种情况下使用委托?该如何解决

2012-03-23 
何种情况下使用委托?不管了MSDN上的例子 还是C#高级编程里的例子 都看了下...感觉为什么一定要使用委托呢?

何种情况下使用委托?
不管了MSDN上的例子 还是C#高级编程里的例子 都看了下...
感觉为什么一定要使用委托呢?正常的方式去调用类里另外一个方法不是一样么?
如果你要说可以多次new委托,达到复用?那么代码量没有减少,性能会有提升?

什么样的情况下我需要使用委托或者匿名方法?
拿eventhandler来说,我初步的理解它也就是一个参数是sender和e的方法
比如我这样的代码:

C# code
        public void Init(HttpApplication application)        {            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));            application.EndRequest += (new EventHandler(this.Application_EndRequest));        }        // Your BeginRequest event handler.        private void Application_BeginRequest(Object source, EventArgs e)        {            //do something;        }        // Your EndRequest event handler.        private void Application_EndRequest(Object source, EventArgs e)        {            //do something;        }


我完全可以不那样写啊,我简单的写成如下形式不一样的意思吗?
C# code
        public void Init(HttpApplication application)        {            application.BeginRequest += Application_BeginRequest();            application.EndRequest += Application_EndRequest();        }        // Your BeginRequest event handler.        private void Application_BeginRequest(Object source, EventArgs e)        {            //do something;        }        // Your EndRequest event handler.        private void Application_EndRequest(Object source, EventArgs e)        {            //do something;        }


上面的代码只是说明一下我的意思,不要深究里面的错误...我的意思就是说我完全可以在Init事件里去掉我要用的方法,而不使用委托。。。
所以回到这个问题
什么样的情况下我需要使用委托或者匿名方法?

[解决办法]
引用楼主 mmbf001 的帖子:
我的意思就是说我完全可以在Init事件里去掉我要用的方法,而不使用委托。。。

[解决办法]
嗯,事实是很多时候,你要使用的方法并不确定
抄袭某位前辈的代码
假设有和欢迎的函数,你想使它在中国用户使用的时候用中文问好,在老外使用的时候用E文问好

 如果不使用委托,你要编写两个函数
 
static void welcome()
{
welcomeInChinese();

或者
static void welcome()
{
welcomeInEnglish();
}


static void welcomeInChinese()
{
Console.WriteLine("欢迎您的使用");
  
  
}
static void welcomeInEnglish()
{
Console.writeLine("Welcome to use!");
}

嗯,如果这样的话,你的代码的适应性就很差,至于为什么··请看下面
 
假如我们定义一个委托
delegate void myDel(); //委托是一个类,委托的变量是方法.

修改前面的欢迎函数定义 

static void welcome(myDel a )
{
a();
}

当遇见老外的时候,就把 welcomeInEnglish 这个变量(额,就当他是变量吧)传给a,如果是中国人,就传
welcomeInChinese .

这样代码的适应性就很强了。
至于为什么?
很简单,假如你不使用委托,你如何实现动态的调用不同的函数来服务不同的客户? 除了直接修改代码,你还能做什么?
用了委托,你就可以动态的调用函数,而不需要去修改代码了
用个if就行
if(中国客户)
{
welcome(welcomeInChinese) ;//委托变量存储的是方法

}
else
{
welcome(welcomeInEnglish);
}
 
 
[解决办法]
看来你完全没有理解委托...你的第二种写法只是Lambda的语法糖,叫做匿名委托...还是委托,换汤不换药...

委托是给其他调用者使用的,它的最大特点是调用者不知道什么时候该调用它,所以只好提前订阅它然后做自己的事不去管它...当委托对象有了订阅者感兴趣的消息就会通知调用者...这是方法不能很容易做到的...

想象一下订阅报纸或牛奶的过程...去看看Windows消息机制和事件驱动机制将有助于你理解委托...
[解决办法]

[解决办法]
似乎上面说的不够透彻(不用委托也能实现动态的调用哈),,用委托能带来很多好处,但个人水平也就那样了,等高手····
------解决方案--------------------


找了个例子,一起学习:
重点是在调用的时候要实例化,指定这个delegate 要做什么事情。
delegate 参数知道结果是什么样的就等了。

这样做的话好处是
1.在执等的时候可指定给什么方法,代码比较好看,重用比较好。

比如我要有一个降XU,只要传一个委托参数,不用再写static public void SortJianXU



using System;
namespace BubbleSorter
{
delegate bool CompareOp(object lhs, object rhs);

class MainEntryPoint
{
static void Main()
{
Employee [] employees =
{
new Employee("Bugs Bunny", 20000),
new Employee("Elmer Fudd", 10000),
new Employee("Daffy Duck", 25000),
new Employee("Wiley Coyote", /*(decimal)*/1000000.38m),
new Employee("Foghorn Leghorn", 23000),
new Employee("RoadRunner'", 50000)};
CompareOp employeeCompareOp = new CompareOp(Employee.RhsIsGreater);
BubbleSorter.Sort(employees, employeeCompareOp);

for (int i=0 ; i<employees.Length ; i++)
Console.WriteLine(employees[i].ToString());
Console.ReadLine();
}
}

class Employee // : object
{
private string name;
private decimal salary;

public Employee(string name, decimal salary)
{
this.name = name;
this.salary = salary;
}

public override string ToString()
{
return string.Format(name + ", {0:C}", salary);
}

public static bool RhsIsGreater(object lhs, object rhs)
{
Employee empLhs = (Employee) lhs;
Employee empRhs = (Employee) rhs;
return (empRhs.salary > empLhs.salary) ? true : false;
}
}

class BubbleSorter
{
static public void Sort(object [] sortArray, CompareOp gtMethod)
{
for (int i=0 ; i<sortArray.Length ; i++)
{
for (int j=i+1 ; j<sortArray.Length ; j++)
{
if (gtMethod(sortArray[j], sortArray[i]))
{
object temp = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = temp;
}
}
}
}
}
}
[解决办法]
可能是便于系统的封装吧,就像button的Click事件,我们通常写的都是事件的处理过程,还有很多代码是系统的~~
[解决办法]
当一个方法执行时,要通知其它的方法时,而要通知的方法的个数是不确定的时候,这就用到委托了。委托与事件是联系比较紧密的一般配合使用
所以学习委托也要学习事件。建议你看一下《大话设计模式》中的观察者模式。里面有详解。很不错的啊。
[解决办法]
.net中的委托可以被当成c++里面的回调函数(参考Array.Sort方法和Interop时的回调函数的处理),
也可以被当成java等里面的观察者(参考事件),
而且在很多需要跨越上下文的调用是都必须使用委托(参考Thread.Start方法)

另外,委托也可被用来在线程池里面执行某个方法(参考BeginInvoke和EndInvoke方法),
以及由于委托的性能接近于调用虚方法的执行效率,可以被当作动态生成的方法的最好载体(参考DynamicMethod.CreateDelegete方法)
[解决办法]
此贴必被推荐,我来助阵的
[解决办法]
其实有的时候是看个人的习惯了
[解决办法]
此贴必被推荐,我来助阵的
[解决办法]
委托可以简单看成是一个封装了的会自动增长和缩短的托管函数指针列表

C# code
->A  B  C  ...
[解决办法]
这里我有一点不成熟的分析
http://topic.csdn.net/u/20081001/13/f581fa25-b929-4739-9fa0-84d65e5c49ee.html
[解决办法]
探讨
委托可以简单看成是一个封装了的会自动增长和缩短的托管函数指针列表
C# code->A
B
C
...
主要用在子线程操作主线程UI控件和作为回调函数




[解决办法]
帮顶一下
[解决办法]
当你想让别人用他特有的方法做事的时候,可以使用委托!
[解决办法]
引用楼主 mmbf001 的帖子:
不管了MSDN上的例子 还是C#高级编程里的例子 都看了下...
感觉为什么一定要使用委托呢?正常的方式去调用类里另外一个方法不是一样么?
如果你要说可以多次new委托,达到复用?那么代码量没有减少,性能会有提升?

什么样的情况下我需要使用委托或者匿名方法?
拿eventhandler来说,我初步的理解它也就是一个参数是sender和e的方法
比如我这样的代码:
C# codepublicvoidInit(HttpApplication application)
{


[解决办法]
此贴必被推荐,我来助阵的
[解决办法]
一、委托
委托类似于函数指针,但函数指针只能引用静态方法,而委托既能引用静态方法,也能引用实例方法。

委托使用分三步:1、委托声明。2、委托实例化。3、委托调用。
例程一:
using System;

namespace 委托
{
delegate int NumOpe(int a,int b); //委托声明
class Class1
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
NumOpe p1 = new NumOpe(c1.Add); //委托实例化
Console.WriteLine(p1(1,2)); //委托调用
Console.ReadLine();
}

private int Add(int num1,int num2)
{
return(num1+num2);
}
}
}
例中,委托NumOpe引用了方法Add。
委托声明了以后,就可以象类一样进行实例化,实例化时把要引用的方法(如:Add)做为参数,这样委托和方法就关联了起来,就可以用委托来引用方法了。
委托和所引用的方法必须保持一致:
1、参数个数、类型、顺序必须完全一致。
2、返回值必须一致。

二、事件

事件有很多,比如说鼠标的事件:MouserMove,MouserDown等,键盘的事件:KeyUp,KeyDown,KeyPress。

有事件,就会有对事件进行处理的方法,而事件和处理方法之间是怎么联系起来的呢?委托就是他们中间的桥梁,事件发生时,委托会知道,然后将事件传递给处理方法,处理方法进行相应处理。

比如在WinForm中最常见的是按钮的Click事件,它是这样委托的:this.button1.Click += new System.EventHandler(this.button1_Click);按按钮后就会出发button1_Click方法进行处理。EventHandler就是系统类库里已经声明的一个委托。

三、自定义事件及其处理

EventHandler以及其它自定义的事件委托都是一类特殊的委托,他们有相同的形式:

delegate void 事件委托名(object sender,EventArgs e);

object用来传递事件的发生者,比如二中的Button控件就是一个事件发生者;EventArgs用来传递事件的细节。

例程二:
using System;

namespace 最简单的自定义事件
{
/// <summary>
/// 事件发送类
/// </summary>
class Class1
{
public delegate void UserRequest(object sender,EventArgs e); //定义委托
public event UserRequest OnUserRequest; //定义一个委托类型的事件

public void run()
{
while(true)
{
if(Console.ReadLine()=="a")
{//事件监听
OnUserRequest(this,new EventArgs()); //产生事件
}
}
}
}

/// <summary>
/// 事件接收类
/// </summary>
class Class2
{
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.OnUserRequest += new Class1.UserRequest(c1_OnUserRequest); //委托实例化后绑定到事件
c1.run();
}

private static void c1_OnUserRequest(object sender, EventArgs e)
{//事件处理方法
Console.WriteLine("\t你触发了事件!");
}
}
}
例程三:
using System;

namespace 带事件数据的事件
{
/// <summary>
/// 带事件数据的事件类,从EventArgs继承


/// </summary>
class OnUserRequestEventArgs:EventArgs
{
private string inputText;
public string InputText
{
get
{
return inputText;
}
set
{
inputText = value;
}
}
}

/// <summary>
/// 事件发送类
/// </summary>
class Class1
{
public delegate void UserRequest(object sender,OnUserRequestEventArgs e);
public event UserRequest OnUserRequest;

public void run()
{
while(true)
{
Console.WriteLine("请输入内容:");
string a=Console.ReadLine();
//if(a=="a")
//{
OnUserRequestEventArgs e1 = new OnUserRequestEventArgs();
e1.InputText = a;
OnUserRequest(this,e1);
//}
}
}
}

/// <summary>
/// 事件接收类
/// </summary>
class Class2
{
[STAThread]
static void Main(string[] args)
{
Class1 c1 = new Class1();
c1.OnUserRequest += new Class1.UserRequest(c1_OnUserRequest);
c1.run();
}

private static void c1_OnUserRequest(object sender, OnUserRequestEventArgs e)
{
Console.WriteLine("\t你输入的是:"+e.InputText);
}
}
}
例程三跟例程二唯一的差别在于自定义了一个类OnUserRequestEventArgs,从EventArgs继承。
[解决办法]
ding
[解决办法]

探讨
看来你完全没有理解委托...你的第二种写法只是Lambda的语法糖,叫做匿名委托...还是委托,换汤不换药...

委托是给其他调用者使用的,它的最大特点是调用者不知道什么时候该调用它,所以只好提前订阅它然后做自己的事不去管它...当委托对象有了订阅者感兴趣的消息就会通知调用者...这是方法不能很容易做到的...

想象一下订阅报纸或牛奶的过程...去看看Windows消息机制和事件驱动机制将有助于你理解委托...

[解决办法]
学习下,强顶!
[解决办法]
简单的来说,程序想回调的时候需要用到委托...
[解决办法]
学习..
[解决办法]
好帖,顶
[解决办法]
就好比你要租房子,又不认识有房子的人,你就需要找房介机构。这里房介机构就充当了委托的功能
LZ 好好再理解一下,应该就可以明白的
[解决办法]

好帖,顶

[解决办法]
一切归于基础.理解下委托机制就什么都知道了
[解决办法]
.
[解决办法]
mark
[解决办法]
需要动态调用方法的时候使用委托,具体使用何种形式的委托,看情况!

事件,其实也是在使用委托!
[解决办法]
成熟的人做成熟的是,工程师应该解决工程问题,而学生才会变来变去地总是破坏他自己的代码。

假设你写一个“我的日程表”的对象,你的日程可能在修改时通知客户它自己被修改了,你会变来变去地为每一个客户而改写这个日程代码吗?那么你不被认为是稳定可靠的合作者。你的代码是成熟的,意味着你的代码从来不需要修改,就能为任何客户做通知服务了!



事件只是委托的稍微复杂一点的封装。

从技术上说,你的日程通知客户,其接口的设计权利在于你,而不是在于客户程序。

从应用上说,当你学习.NET时你无须去学java中盛行的什么云山雾罩的许多设计模式,搞清楚委托(和事件)机制就能发觉那些所谓设计模式纯粹是不懂委托和事件机制的人搞的繁琐设计。
[解决办法]
委托,或者说是回调,或者也可以泛指事件通知机制,是设计上非常基本的技术,你掌握了对象之间的依赖关系倒转的简单技术,就掌握了非常大的设计自由度,就好像是非黑白对于你来说不再是人生约束而只是一种游戏,设计软件架构时就不学究而会非常轻松地因客户需求的改变而任意安排你的程序之间的先后开发次序和依赖关系。
[解决办法]
大牛出现了,不容易啊

我来顶一下
[解决办法]
牛人说话就是一针见血!





[解决办法]
委托可以为一个事件定义任意多个处理函数

热点排行