解释代理如何在以下代码中工作?

时间:2009-03-11 21:11:28

标签: c# .net delegates

我很好奇下面的代码如何工作,特别是包含委托内容的部分,因为我是新手。此外,代码中是否存在任何瓶颈,例如,使用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 个答案:

答案 0 :(得分: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++;
        }
    } 

请注意,此代码效率有点低,因为两个不同的匿名委托实际上做同样的事情并且可以共享。

答案 1 :(得分:2)

实际上,那里的代表比你期望的多。 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;
            }))

我们正在使用谓词; “给定一个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 :(得分:0)

它是一个匿名委托,作为查找表达式的选择标准。换句话说,如果颜色等于name给出的颜色,它将返回true,Find将把它添加到它正在生成的IEnumerable中。如果返回false,则Find将不包含它。

可以更简洁地写出来
p => p.ColorCode == name

答案 3 :(得分:0)

存在和查找是通用扩展方法。它们用于集合中每个项目的每个循环。传递委托一个参数(定义为“(ColorData e)”),并返回一个布尔值。

答案 4 :(得分:0)

代表:

此示例中的委托正在实现Func方法。基本上,你正在做的是创建一个采用ColorData参数的方法,并返回一个bool。

这使您可以对IEnumerable集合的每个成员执行Exists()和Find()调用以进行检查和过滤。

排序词典:

如果这是你使用它的唯一地方,你最好使用SortedDictionary,因为你不会经常使用它。现在,每次你打电话给ColorCodes,你都会使用。 SortedDictionary将不断排序。