不管了MSDN上的例子 还是C#高级编程里的例子 都看了下...
感觉为什么一定要使用委托呢?正常的方式去调用类里另外一个方法不是一样么?
如果你要说可以多次new委托,达到复用?那么代码量没有减少,性能会有提升?什么样的情况下我需要使用委托或者匿名方法?
拿eventhandler来说,我初步的理解它也就是一个参数是sender和e的方法
比如我这样的代码: 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;
}
我完全可以不那样写啊,我简单的写成如下形式不一样的意思吗? 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事件里去掉我要用的方法,而不使用委托
所以回到这个问题
什么样的情况下我需要使用委托或者匿名方法?
感觉为什么一定要使用委托呢?正常的方式去调用类里另外一个方法不是一样么?
如果你要说可以多次new委托,达到复用?那么代码量没有减少,性能会有提升?什么样的情况下我需要使用委托或者匿名方法?
拿eventhandler来说,我初步的理解它也就是一个参数是sender和e的方法
比如我这样的代码: 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;
}
我完全可以不那样写啊,我简单的写成如下形式不一样的意思吗? 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事件里去掉我要用的方法,而不使用委托
所以回到这个问题
什么样的情况下我需要使用委托或者匿名方法?
这个代码的意思不是在Init里面调用Application_BeginRequest和Application_EndRequest方法,而是在
开始请求的时候再调用Application_BeginRequest,结束请求的时候去调用Application_EndRequest public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
抄袭某位前辈的代码
假设有和欢迎的函数,你想使它在中国用户使用的时候用中文问好,在老外使用的时候用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);
}
既然我要给BeginRequest加上一个动作(方法),那么我在这个BeginRequest方法内调用我要用的即Application_BeginRequest不是一样么?
这样写是一样实现功能,但是为什么要这么复杂的写呢?
直接if(中国客户)
{
welcomeInChinese() ;
}
else
{
welcomeInEnglish();
}
...省一个delegate 省一个welcome()......囧......
搞不懂了...查了下资料说在设计大型应用程序时使用委托和事件可以减少依赖性和层的关联...
不知道是否有人在实际项目中使用过委托,那么是在何种情况下让你使用委托的....
重点是在调用的时候要实例化,指定这个delegate 要做什么事情。
delegate 参数知道结果是什么样的就等了。这样做的话好处是
1.在执等的时候可指定给什么方法,代码比较好看,重用比较好。比如我要有一个降XU,只要传一个委托参数,不用再写static public void SortJianXUusing 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;
}
}
}
}
}
}
也可以被当成java等里面的观察者(参考事件),
而且在很多需要跨越上下文的调用是都必须使用委托(参考Thread.Start方法)另外,委托也可被用来在线程池里面执行某个方法(参考BeginInvoke和EndInvoke方法),
以及由于委托的性能接近于调用虚方法的执行效率,可以被当作动态生成的方法的最好载体(参考DynamicMethod.CreateDelegete方法)
->A
B
C
...
主要用在子线程操作主线程UI控件和作为回调函数
http://topic.csdn.net/u/20081001/13/f581fa25-b929-4739-9fa0-84d65e5c49ee.html
在运行时你不一定知道外面会提供哪个方法(函数), 不是在内部假定调用哪个, 而是调用一个符合约定的函数就行,
约定就是通过 delegate 来描述的, 也就是 C++ 里头的函数指针, callback,
而外部实现的函数可以通过 delegate 实例的方式传递进来// 定义一个用于比较两个对象的函数原型(delegate)
// op1 > op2 返回 大于 0 的数
// op1 = op2 返回 0
// op1 < op2 返回小于0的数
delegate int comparehandler(object op1, object op2);// 函数参数为一个 comparehandler 实例, 也就是一个具体的函数实现
// 不管球它是哪个类的哪个函数, 只要符合 comparehandler 的签名(signature)就行
void somefunction(comparehandler ch)
{
//..
// 对函数内部对象 object1 , object2 比较
// 这里不管具体实现, 运行时可以传递任意实现来玩耍
int result = ch(object1, object2);
}
当编写基础代码时, 这样的范式很常用, 有时需要一个功能, 但由于某种原因, 在模块内不能实现时,
就可以采用这种参数化的方式.
委托类似于函数指针,但函数指针只能引用静态方法,而委托既能引用静态方法,也能引用实例方法。
委托使用分三步: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继承。
第一种和第二种写法全部都是在注册委托(使得事件与具体的实现关联)。
虽然没有写New EventHandler(),但是编译器已经能够自动识别函数的签名,然后发现与事件声明的委托签名相同,因此注册。
后面.net的匿名类型、隐式转换也有些类似,就是说,你无需指定类型的签名,编译器已经可以自动去正确推测了.
与多线程编程中的异步方法原理一样,B在发送消息调用A提供的事件后,不必等待,可以接着处理自己的事情,等A的事件
结束后,将结果通过消息传递给B。