请解释.NET代表

时间:2010-03-19 01:26:22

标签: c# .net delegates action

所以我读了MSDN和Stack Overflow。我理解Action Delegate一般会做什么,但不管我做了多少个例子都不点击。一般来说,代表的想法也是如此。所以这是我的问题。当你有这样的功能时:

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

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

9 个答案:

答案 0 :(得分:9)

它需要一个接受IEnumerable和Exception并返回void的函数。

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

GetCustomers(SendExceptionToCustomers);
不过,GetCustomers似乎是这个函数的一个可怕的名字 - 它要求一个动作,所以它更像是DoSomethingToCustomers

编辑以回应评论


  

Ok有道理,那么现在为什么还要为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,并传递它

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确实检索客户,但是异步。每当检索到客户时,如果发生异常,它会调用您使用客户列表或异常提供的功能。

答案 1 :(得分:3)

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

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

第二个函数必须采用IEnumerable<Customer>Exception类型的两个参数。

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

例如:

static void GetCustomersCallback(IEnumerable<Customer> customers, Exception ex) {
    //Do something...
}

//Elsewhere:
GetCustomers(new Action<IEnumerable<Customer>,Exception>(GetCustomersCallback));

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

GetCustomers(GetCustomersCallback);

答案 2 :(得分:2)

你可以用lambda

来调用它
GetCustomers((cust, ex) => {
    //do something here}
);

答案 3 :(得分:2)

答案 4 :(得分:1)

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

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

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

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

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

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

答案 5 :(得分:1)

只需?函数指针

答案 6 :(得分:0)

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

说你有这个方法:

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

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

GetCustomers(DoSomeStuffWithCustomers);

答案 7 :(得分:0)

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

  1. Andrew Troelsen在Pro C# 2008 and the .Net 3.5 Platform
  2. 中对他们的解释
  3. Head First Design Patterns
  4. 中关于观察者模式的章节

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

答案 8 :(得分:0)

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