带代理的代码说明

时间:2014-09-22 22:26:31

标签: c# delegates

我读了很多关于代表的文章,是的,起初语法很混乱。我发现 this article the most useful. 示例2 使得如何使用委托变得非常容易理解。但我已经将这些代码提供给我并使用它:

public delegate bool IntPredicate(int x);
public delegate void IntAction(int x);

class IntList : List<int>
{
    public IntList(params int[] elements) : base(elements)
    {

    }

    public void Act(IntAction f)
    {
        foreach (int i in this)
        {
            f(i);
        }
    }
    public IntList Filter(IntPredicate p)
    {
        IntList res = new IntList();
        foreach (int i in this)
            if (p(i))
                res.Add(i);
        return res;
    }
}

现在,让我感到困惑的是fp函数中的ActFilter变量。在教程中,这些函数似乎是正常的,具有正常类型的属性,但这里的属性属于委托函数类型,我会受到混淆。

请你就此事劝我一下吗?

2 个答案:

答案 0 :(得分:3)

委托只是一种类型。使用您习惯的类型(例如intstring等),当您想要使用它们时,您可以使用框架中的一个或者声明自己的类型。您可以对代理执行完全相同的操作 - 使用预先构建的代理(如System.Action)或声明您自己的代码,这是在此处完成的。

因此,在您的代码段中,声明了3种类型:

public delegate bool IntPredicate(int x);
public delegate void IntAction(int x);

class IntList : List<int> { ... }

您会注意到委托声明与类声明处于同一级别。

如果您有类型(如此处的IntPredicate),则可以将其用于变量或函数参数。现在的问题是:你如何设置变量的值,然后用它做什么?

使用普通变量,您只需传入值。像这样:

string text = "Hello world";

原则与代理相同,但是,当然,你必须传递一些委托类型或可以转换为它的东西。您有几种选择:

现有方法

如果方法的签名(即返回值和参数)与委托的签名匹配,则可以传入方法。所以,你可以这样做:

void WriteIntAction(int value)
{
    Console.WriteLine(value);
}

/* then, in some other method */
IntList intList = new IntList(1,2,3);
intList.Act(WriteIntAction);

匿名方法

有几种方法可以创建匿名方法。我将使用lambda表达式,因为这是最简单的。如果你曾经使用过任何函数式语言,那就应该很熟悉了。

IntList intList = new IntList(1,2,3);
intList.Act(x => Console.WriteLine(x));

因此,在使用您需要的方法(无论是现有方法还是匿名方法)设置变量后,您可以像使用任何方法一样使用委托变量。这就是这一行:

f(i);

请注意,委托是一种引用类型,因此f的值可以是null,当您尝试调用委托时,它会抛出异常。

<强> TL; DR

委托是一种类型。您可以在变量或方法参数中使用它。您可以仅使用其名称传递方法,也可以创建匿名方法。然后,您可以像使用方法一样使用变量来调用传递给它的方法。

您可以在线阅读更多内容,例如:http://msdn.microsoft.com/en-us/library/ms173171.aspx

答案 1 :(得分:1)

对于所有意图和目的,委托类型只是一个函数(或者如果您是C ++用户,则类似于函数指针)。换句话说,你将它们称为函数,就像示例代码所做的那样。

f(i)调用传递的函数,并将i变量作为其唯一参数,就像它看起来一样。