c# - 与委托(delegate)一起解释这段代码

标签 c# delegates

我读了很多关于委托(delegate)的文章,是的,一开始语法很困惑。我找到了 this article the most useful. 示例 2 使如何使用委托(delegate)变得非常容易理解。但是我已经获得了这段代码并使用了它:

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

现在,让我感到困惑的是 ActFilter 函数中的 fp 变量。在教程中,那些函数看起来很正常,它们的属性类型也很正常,但这里的属性是委托(delegate)函数类型,我感到很困惑。

你能就这件事给我一些启发吗?

最佳答案

委托(delegate)只是一种类型。对于您习惯使用的类型(如 intstring 等),当您想要使用它们时,您要么使用框架中的类型,要么声明你自己。您可以对委托(delegate)执行完全相同的操作 - 使用预构建的委托(delegate)(如 System.Action)或声明您自己的委托(delegate),这就是此处所做的。

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

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

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

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

当你有一个类型(比如这里的IntPredicate)时,你就可以将它用于变量或函数参数。现在的问题是:如何设置变量的值,然后用它做什么?

对于普通变量,您只需传入值即可。像这样:

string text = "Hello world";

委托(delegate)的原理是一样的,当然,你必须传入委托(delegate)类型的东西或者可以转换成它的东西。您有多种选择:

现有方法

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

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

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

f(i);

只是要注意delegate是一个引用类型,所以这里的f的值可以是null,当你尝试调用一个delegate时会抛出异常.

长话短说

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

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

关于c# - 与委托(delegate)一起解释这段代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25984023/

相关文章:

jquery - 将多个参数传递给 $.delegate

c# - Marshal.PtrToStructure 访问冲突

c# - 如何在没有 GAC 的情况下使用 ApplicationManager 加载对象?

c# - 如何将 MSSQL_CERTIFICATE_STORE 从一台机器移动到另一台机器?

C# – try{}catch(Exception ex){} – 不捕获任何异常

Kotlin - 委托(delegate)链

c# - 如何将事件传递给 C# 中的函数?

c# - 为什么在DisplayNameFor()中需要lambda表达式?

ios - 两个容器 View 之间的委派

iOS:委托(delegate) VC 不直接连接到其他 VC 的委托(delegate)困境