我阅读了MSDN和Stack Overflow。我大致理解Action Delegate的作用,但无论我做多少个例子,它都不是那么顺畅。对于代理的概念也是如此。所以这是我的问题。当你有一个像这样的函数:
public GetCustomers(Action<IEnumerable<Customer>,Exception> callBack)
{
}
这是什么,我应该传递什么给它?
void SendExceptionToCustomers(IEnumerable<Customer> customers, Exception ex) {
foreach(var customer in customers)
customer.SendMessage(ex.Message);
}
GetCustomers(SendExceptionToCustomers);
顺便提一下,GetCustomers 这个函数名看起来很糟糕——它要求执行一个动作,所以更像是 DoSomethingToCustomers。
编辑 回复评论
好的,这很有道理。那么为什么还要使用 GetCustomer 函数呢?如果我只是将其重命名为 GetCustomer,难道不能实现同样的功能吗?
嗯,这里发生的情况是调用者可以指定某些操作。假设 GetCustomers 是这样实现的:
public void GetCustomers(Action<Enumerable<Customer>, Exception> handleError) {
Customer[] customerlist = GetCustomersFromDatabase();
try {
foreach(var c in customerList)
c.ProcessSomething()
} catch (Exception e) {
handleError(customerList, e);
}
}
GetCustomers((list, exception) => {
Console.WriteLine("Encountered error processing the following customers");
foreach(var customer in list) Console.WriteLine(customer.Name);
Console.WriteLine(exception.Message);
});
尽管您可以从远程应用程序中调用GetCustomers并传递参数,
Getcustomers((list, exception) => {
// code that emails me the exception message and customer list
})
static void GetCustomersCallback(IEnumerable<Customer> customers, Exception ex) {
//Do something...
}
//Elsewhere:
GetCustomers(new Action<IEnumerable<Customer>,Exception>(GetCustomersCallback));
这个调用会创建一个新的委托实例,指向GetCustomersCallback
函数,并将该委托传递给GetCustomers
函数。预计在客户加载完成后,GetCustomers
将调用回调函数,并将已加载的客户作为参数传递。
您还可以省略委托实例化并直接传递函数:
GetCustomers(GetCustomersCallback);
System.Delegate
是一个类;你可以在Reflector中看到它。 - SLaks你可以使用lambda表达式来调用它
GetCustomers((cust, ex) => {
//do something here}
);
简单易懂?函数指针
这只是C语言函数指针的更新版本,如果它是非静态对象方法指针,则可以将其绑定到对象实例(C++在添加对象和函数指针时称之为方法指针)。
使用C#的泛型功能可以使类型签名通用化。
所有泛型内容都只是对签名进行模板化。
名称委托选择不当(除非您认为我们所有的应用程序都由框架驱动)。因为使用并不总是“委托”。往往是您已经委派某些责任的代码(例如迭代器)调用您先前发送的“委托”。这就是为什么您经常看到术语回调的原因。
传统上,在框架中使用回调来调用您的应用程序代码,以便在循环中间或发生特定事件时调用。它允许您在其他代码的中间发生您的代码-实际上,这几乎是线程内唯一的方法。
显然,.NET事件处理程序是由框架在适当的时间调用的委托,并且您可以在函数中接受委托并适当地调用它们,以使您的代码有些通用/可重用/有组织。
public void DoSomeStuffWithCustomers(
IEnumerable<Customer> customers, Exception exception)
{
}
GetCustomers(DoSomeStuffWithCustomers);
在我阅读以下内容之前,它们让我感到非常困惑:
第二本书是关于Java的,并没有提到委托,但它很好地解释了委托有助于解决的问题:类之间的通信。
有关DotNet委托和事件的详细信息,请参阅以下链接: http://www.codeproject.com/KB/cs/Delegate_To_Event_in_CS.aspx
GetCustomers
函数在后台加载客户端,然后在完成时调用回调函数并将已加载的客户端传递给它。 - SLaks