请解释.NET代表

所以我读了MSDN和Stack Overflow。 我理解Action Delegate的一般操作,但无论我做多少例子都不会点击。 一般来说,代表的想法也是如此。 所以这是我的问题。 当你有这样的function:

public GetCustomers(Action<IEnumerable,Exception> callBack) { } 

这是什么,我应该传递给它什么?

它期望一个获取IEnumerable和Exception并返回void的函数。

 void SendExceptionToCustomers(IEnumerable customers, Exception ex) { foreach(var customer in customers) customer.SendMessage(ex.Message); } GetCustomers(SendExceptionToCustomers); 

顺便说一句,GetCustomers似乎是这个function的一个可怕的名字 – 它要求一个动作,所以它更像是DoSomethingToCustomers

编辑回应评论


好有道理,现在为什么还要为GetCustomerfunction而烦恼呢? 如果我只是将它重命名为GetCustomer,我不能用你的function做同样的事情吗?

那么,这里发生的是调用者可以指定一些动作。 假设GetCustomers实现如下:

 public void GetCustomers(Action, Exception> handleError) { Customer[] customerlist = GetCustomersFromDatabase(); try { foreach(var c in customerList) c.ProcessSomething() } catch (Exception e) { handleError(customerList, e); } } 

那么你可以在命令行程序的某个地方调用Getcustomers,然后传递它

 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 }) 

此外,Slak的评论提出了委托参数的另一个原因 – GetCustomers确实检索客户,但是异步。 每当检索到客户时,如果发生exception,它会使用客户列表或exception调用您提供的function。

委托是指向一个或多个function的类。 可以调用委托实例,该实例将调用它指向的函数。

在您的情况下, GetCustomers函数将第二个函数作为参数。

第二个函数必须采用IEnumerableException类型的两个参数。

要调用GetCustomers ,您需要为它调用第二个函数,然后传递一个包含第二个函数的委托。

例如:

 static void GetCustomersCallback(IEnumerable customers, Exception ex) { //Do something... } //Elsewhere: GetCustomers(new Action,Exception>(GetCustomersCallback)); 

此调用创建一个指向GetCustomersCallback函数的新委托实例,并将该委托传递给GetCustomers函数。 GetCustomers可能会在客户完成加载后调用回调,并将加载的客户作为参数传递。
您也可以省略委托实例化并直接传递函数:

 GetCustomers(GetCustomersCallback); 

你可以用lambda来调用它

 GetCustomers((cust, ex) => { //do something here} ); 

.NET代表:睡前故事

它只是C函数指针的更新版本,如果它是非静态对象方法指针(C ++在将对象和函数指针组合在一起时称为方法指针),则可能将其绑定到对象实例。

使用C#的通用function可以使类型签名成为通用的。

所有仿制药都只是模仿签名。

名称委托选择不当(除非您认为我们的所有应用程序都是由框架驱动的)。 因为使用并不总是“委托”。 通常情况下,您委托的代码(一个迭代器,比如说)会调用您之前发送的“委托”。这就是为什么您经常看到术语回调的原因。

回调传统上一直用在框架中,以便在循环中或特定事件发生时调用应用程序代码。 它允许您让代码在其他代码中间发生 – 实际上,它只是线程中的唯一方法。

显然,.NET事件处理程序是框架在适当的时候调用的委托,您可以在函数中接受委托并调用它们,以使您的代码具有某种通用性/可重用性/组织性。

只是? 函数指针

你会传递一个void方法,它将IEnumerable和Exception作为参数…

说你有这个方法:

 public void DoSomeStuffWithCustomers( IEnumerable customers, Exception exception) { } 

您可以像这样调用GetCustomers方法:

 GetCustomers(DoSomeStuffWithCustomers); 

在我读到之前,他们把我弄糊涂了:

  1. Andrew Troelsen在Pro C#2008和.Net 3.5平台上对它们的解释
  2. 头部优先设计模式中观察者模式的章节

第二本书是关于java的,并没有提到委托,但它解释了委托帮助解决的问题:类之间的沟通。

有关DotNet代表和事件的详细信息,请参阅链接: http : //www.codeproject.com/KB/cs/Delegate_To_Event_in_CS.aspx