2010-07-16 124 views
2

我已经从Microsoft下载了VCSharpSample包,并开始阅读匿名代理。我可以或多或少地理解代码正在做什么,但我不明白其背后的原因。也许如果你给了我一些例子,它会导致更简洁的代码和更容易的可维护性,那么我可以围绕它来包裹我的头。 :)请帮我理解匿名代表?

你能帮忙吗?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 
{ 
    delegate decimal CalculateBonus(decimal sales); 

    class Player 
    { 
     public string Name; 
     public decimal Score; 
     public decimal Bonus; 
     public CalculateBonus calculation_algorithm; 
    } 

    class Program 
    {   
     static decimal calculateStandardBonus(decimal sales) 
     { 
      return sales/10; 
     } 

     static void Main(string[] args) 
     { 
      decimal multiplier = 2; 

      CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus); 
      CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales/10; }; 

      Player[] players = new Player[5]; 

      for (int i = 0; i < 5; i++) 
      { 
       players[i] = new Player(); 
      } 

      players[0].Name = "Sergio"; 
      players[0].Score = 240; 
      players[0].calculation_algorithm = standard_bonus; 

      players[1].Name = "Sergio"; 
      players[1].Score = 240; 
      players[1].calculation_algorithm = enhanced_bonus; 

      players[2].Name = "Caro"; 
      players[2].Score = 89; 
      players[2].calculation_algorithm = standard_bonus; 

      players[3].Name = "Andy"; 
      players[3].Score = 38; 
      players[3].calculation_algorithm = enhanced_bonus; 

      players[4].Name = "Hugo"; 
      players[4].Score = 600; 
      players[4].calculation_algorithm = enhanced_bonus; 

      foreach (Player player in players) 
      { 
       PerformCalculationBonus(player); 
      } 

      foreach (Player player in players) 
      { 
       DisplayPersonalDetails(player); 
      } 

      Console.ReadLine(); 
     } 

     public static void PerformCalculationBonus(Player player) 
     { 
      player.Bonus = player.calculation_algorithm(player.Score); 
     } 

     public static void DisplayPersonalDetails(Player player) 
     { 
      Console.WriteLine(player.Name); 
      Console.WriteLine(player.Score); 
      Console.WriteLine(player.Bonus); 
      Console.WriteLine("---------------"); 
     } 
    } 
} 

回答

8

匿名代理旨在帮助您通过在另一个方法中内联定义简单委托的行为来使代码更具可读性。这意味着如果你正在处理需要委托的事情(例如事件处理程序),则可以在代码中正确定义行为,而不是为其创建专用功能。

另外,它们是lambda表达式的前兆。像LINQ to Objects(对IEnumerable<T>进行操作的任何方法)都使用委托对对象执行查询。举例来说,如果你有一个字符串的集合,你想的是发现所有的人都认为是5个字符,你可以做到这一点与拉姆达查询:

List<string> strings = ... 

var query = strings.Where(s => s.Length == 5); 

或者你可以用匿名委托做:

var query = strings.Where(delegate(string s) { return s.Length == 5; }); 

如果你没有这些,你的代码会是这个样子:

var query = strings.Where(IsFiveCharacters); 

... 

private bool IsFiveCharacters(string input) 
{ 
    return input.Length == 5; 
} 

它实现是很重要的,虽然,lambda表达式和匿名委托只是合作mpiler功能。当你的代码被编译时,确实实际上像上例中那样创建了常规函数,但是它们是隐藏的,并且使用在所使用的语言中是非法的字符命名。当执行诸如闭包(如果你访问lambda /匿名委托声明之外的变量),还有很多逻辑绕过它们。

+0

+1:非常好.. – 2010-07-16 16:08:25

+0

+1爱你的lambda示例。打破它非常好。你认为你可以把它分解成类似的事件吗? – jsmith 2010-07-16 16:10:23

+0

所以它们基本上只在你创建一个只有一行代码的方法时才有用?为了避免看到它每次都做什么? – 2010-07-16 16:12:36

1

的好处是,你没有看别的地方的代码做一次查找/变更/计算/不管。对于只能在一个地方使用的函数(或者一个函数的其他类),添加一个函数(或者其他类)是非常烦人的,然后你必须稍后回顾一下,看看代码是什么以及它为什么是是否需要,是否仍然存在。

对于匿名代理,代码就在使用它的代码中。

+0

啊哈!现在我可以看到它用于这个问题中发布的特定示例。但是,如果所讨论的方法只有一行代码,这不会有用吗? – 2010-07-16 16:10:02

+0

可能。最适合非常小的一次性功能。如果你的匿名函数太大,它也会增加其包含函数的大小 - 并且保持函数很小(这通常是一个好主意)意味着将代码分解成实际函数并按名称使用它。 (如果功能很大,希望你能在其他地方使用它) – cHao 2010-07-16 16:14:51