Объясните, как работают делегаты в следующем коде? - PullRequest
0 голосов
/ 12 марта 2009

Мне любопытно, как работает следующий код, особенно часть, которая содержит делегаты, так как я новичок в этом. Кроме того, есть ли какие-либо узкие места в коде, например, было бы лучше использовать SortedDictionary, чем использовать List и затем сортировать его с помощью 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++;
            }
        } 
    }
}

Ответы [ 5 ]

2 голосов
/ 12 марта 2009

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

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

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

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

который (для LINQ-to-Objects) совпадает с:

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

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


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

    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 мог бы помочь, но не в этом случае, возможно.

2 голосов
/ 12 марта 2009

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

Сначала взгляните на это ColorCodes средство доступа к свойству:

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

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

Сначала мы переберем все строки в этой таблице:

    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 голосов
/ 12 марта 2009

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

0 голосов
/ 12 марта 2009

Участники конференции:

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

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

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

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

0 голосов
/ 12 марта 2009

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

p => p.ColorCode == name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...