2010-07-16 4 views
2

Я загрузил пакет VCSharpSample из Microsoft и начал читать анонимные делегаты. Я могу более или менее понять, что делает код, но я не понимаю причины этого. Может быть, если вы дадите мне несколько примеров, где это приведет к более чистым кодам и упрощению ремонтопригодности, тогда я мог бы обернуть вокруг себя голову. :)Пожалуйста, помогите мне понять анонимных делегатов?

Помогите?

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

Анонимные делегаты призваны помочь вам сделать код более понятным, если вы сможете определить поведение простого делегата inline в другом методе. Это означает, что если вы имеете дело с чем-то, что требует делегата (например, обработчик событий), вы можете определить поведение прямо в коде, а не создавать для него специальную функцию.

Кроме того, они являются предшественниками лямбда-выражений. Такие вещи, как LINQ to Objects (любой из методов, работающих на IEnumerable<T>), используют делегаты для выполнения запросов к объектам. Например, если у вас есть набор строк и вы хотите запрос, который находит все из них, с длиной пять символов, вы можете сделать это с лямбда:

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

это важно понимать, однако, что лямбды и анонимные делегаты просто комп iler. Когда ваш код скомпилирован, он делает фактически создает регулярные функции, как в последнем примере, но они скрыты и называются с использованием символов, которые являются незаконными на используемом языке. Существует много логики, которая идет вокруг них, когда вы делаете такие вещи, как закрытие (где вы получаете доступ к переменной, которая существует вне объявления лямбда-анонимного делегата).

+0

+1: Очень приятно .. –

+0

+1 Любите свой пример лямбда. Сломать его очень приятно. Как вы думаете, вы можете сломать его так же, как в случае с событием? – jsmith

+0

Значит, они в основном полезны, если вы создаете метод, который имеет только одну строку кода? Чтобы не видеть, что он делает каждый раз? –

1

Преимущество в том, что вам не нужно искать где-то еще, чтобы код выполнял одноразовый поиск/изменение/расчет/независимо. Немного раздражает необходимость добавления функции (или целого другого класса для функции!), Которую вы будете использовать только в одном месте, а затем вам придется оглянуться назад и посмотреть, что это за код и почему и все еще есть.

С анонимным делегатом код находится прямо там, в коде, который его использует.

+0

Aha! Теперь я вижу его использование для этого конкретного примера, который я опубликовал в вопросе. Но разве это не было бы полезно, если бы рассматриваемый метод имел только одну строку кода? –

+0

Возможно. Это лучше всего для очень маленьких одноразовых функций. Если ваша анонимная функция слишком велика, она также увеличивает размер ее содержащей функции - и сохранение небольших функций (что обычно является хорошей идеей) означало бы разбить этот код на реальную функцию и использовать ее по имени. (Если функция такая большая, надеюсь, вы все равно сможете ее использовать в любом другом месте.) – cHao

Смежные вопросы