2009-03-11 3 views
0

Мне любопытно, как работает следующий код, особенно часть, содержащая материал делегата, так как я новичок в нем. Кроме того, существуют ли какие-либо узкие места в коде, например, использование SortedDictionary будет лучше, чем использование списка, а затем его сортировка с использованием LINQ? Итак, вот код:Объясните, как делегаты работают в следующем коде?

public class ColorManager 
{ 
    private List<ColorData> colorCodes = new List<ColorData>(); 

    public List<ColorData> ColorCodes 
    { 
     get 
     { 
      var sortList = from a in this.colorCodes 
          orderby a.colorCode ascending 
          select a; 

      return sortList.ToList(); 
     } 
    } 

    public void FillData(DataTable table) 
    { 
     for(int row = 0; row < table.Rows.Count; row++) 
     { 
      ColorData cData = new ColorData(); 
      string name = table.Rows[row]["Color"].ToString().Trim(); 

      if(!this.colorCodes.Exists(
       delegate(ColorData e) 
       { 
        return e.ColorCode == name; 
       })) 
      { 
       cData.Add(table.Rows[row]["Color"].ToString()); 
       this.colorCodes.Add(cData); 
      } 
      else 
      { 
       this.colorCodes.Find(
        delegate(ColorData e) 
        { 
         return e.ColorCode == name; 
        }).Count++; 
      } 
     } 
    } 
} 

ответ

2

Мне любопытно, как работает следующий код, особенно часть, содержащая материал делегата, так как я новичок в нем.

Сначала посмотрим на эту ColorCodes собственность аксессору:

 var sortList = from a in this.colorCodes 
         orderby a.colorCode ascending 
         select a; 

возвращает список всех цветовых кодов (this.colorCodes) в порядке возрастания (...orderby a.colorCode ascending). Простой до сих пор. Как насчет более мясистого метода FillData?

Во-первых, мы перебираем каждой строки в этой таблице:

for(int row = 0; row < table.Rows.Count; row++) 
    { 

Затем, мы будем смотреть на Color колонке текущей строки.

 ColorData cData = new ColorData(); 
     string name = table.Rows[row]["Color"].ToString().Trim(); 

Если столбец не имеет аналогов в нашем списке цветовых кодов, это if условие истинно. Метод Exists принимает функцию с одним аргументом, которая возвращает bool, что и является этим анонимным делегатом: функция с одним аргументом (ColorData e), которая возвращает логическое значение (e.ColorCode == name). Он сбрасывается (!this.[...]), поэтому, если совпадение найдено, условие является ложным.

 if(!this.colorCodes.Exists(
      delegate(ColorData e) 
      { 
       return e.ColorCode == name; 
      })) 
     { 
      cData.Add(table.Rows[row]["Color"].ToString()); 
      this.colorCodes.Add(cData); 
     } 

В противном случае, если есть совпадение, найти имя, используя другой анонимный делегат, и добавьте к отсчету предметов этого цвета.

 else 
     { 
      this.colorCodes.Find(
       delegate(ColorData e) 
       { 
        return e.ColorCode == name; 
       }).Count++; 
     } 
    } 

Обратите внимание, что этот код несколько неэффективен, поскольку два разных анонимных делегата действительно делают одно и то же и могут быть разделены.

+0

Как это можно было бы реорганизовать, чтобы они делились? – Xaisoft

+0

Вы можете использовать анонимный метод везде, где ожидается делегат. Попробуйте var matchThisColor = new Func (e => e.ColorCode == name) ;. –

0

Его анонимный делегат, который служит критерием выбора выражения поиска. В словах, если цвет равен цвету, указанному именем, он вернет true, и Find добавит это в IEnumerable, который он генерирует. Если он вернет false, Find не будет содержать его. Это может быть написано более кратко, так как

p => p.ColorCode == name 
0

Существует и находит общие методы расширения. Они предназначены для каждого цикла над каждым элементом в коллекции. Передача делегату параметра (определенного как «(ColorData e)») и возврат логического значения.

0

Делегаты:

Делегаты в этом примере реализации способа Func. В основном, что вы делаете, создается метод «на лету», который принимает аргумент ColorData и возвращает bool.

Это позволяет вам выполнять вызовы Exists() и Find() для каждого члена вашей коллекции IEnumerable для проверки и фильтрации.

Что касается отсортированного словаря:

Если это единственное место, где вы используете его, вы бы лучше использовать SortedDictionary, так как вы не будете прибегать постоянно. Прямо сейчас, каждый раз, когда вы вызываете ColorCodes, вы прибегаете. СортировкаDictionary будет постоянно сортироваться.

2

На самом деле, там больше делегатов, чем вы ожидаете. Запрос LINQ:

 var sortList = from a in this.colorCodes 
         orderby a.colorCode ascending 
         select a; 

на самом деле:

var sortList = this.colorCodes.OrderBy(a => a.colorCode); 

, который (для LINQ к объектам) такая же, как:

var sortList = this.colorCodes.OrderBy(delegate (ColorData a) { 
    return a.colorCode; 
}) 

Это использует делегат для идентификации элемента для сортировки - т.е. «с учетом ColorData, я дам вам colorCode». Обратите внимание, что многие select используют , также включают делегата, но не в этом случае (тривиальный select a удаляется компилятором).

В коде:

 if(!this.colorCodes.Exists(
      delegate(ColorData e) 
      { 
       return e.ColorCode == name; 
      })) 

мы используем предикат; «учитывая ColorData, я скажу вам, является ли это совпадением, проверяя имя для равенства». Обратите внимание, что здесь name «захвачен» в делегат, что связано с довольно сложными трюками компилятора (я не буду их описывать).


Re эффективность; трудно быть уверенными, но возможно:

Dictionary<string, ColorData> items = new Dictionary<string, ColorData>(); 
    foreach(DataRow row in table.Rows) { 
     string name = row["Color"].ToString().Trim(); 
     ColorData cData; 
     if (items.TryGetValue(name, out cData)) { 
      cData.Count++; 
     } else { 
      cData.Add(name); 
      colorCodes.Add(cData); 
      items.Add(name, cData); 
     } 
    } 

Это позволяет избежать много дублирования, и использует словарь, чтобы найти значение, а не постоянно, используя Contains/Find. Во многих случаях LINQ GroupBy, возможно, помог, но не в этом случае.

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