在 Action 上使用局部函数作为输入参数

Using a Local Function over an Action as an input param

我有一个接受 Action<string> 的方法(参见下面的简单示例),但是在构造 Action 的调用方法中,Resharper 建议应该使用本地函数使用过。

关于使用局部函数代替动作的推荐做法是什么,这重要吗,或者是否有需要注意的陷阱?

public void Caller()
{
    string holder;
    Action<string> act = s => holder = s;
    void SetHolder(string s) => holder = s;

    DoStuff(act);
    DoStuff(SetHolder);
}

public void DoStuff(Action<string> setHolder)
{
    setHolder("holders new string");
}

本地函数相对于委托的好处之一是调用它们不会导致委托实例化和委托调用,这在您的示例中丢失了,因为您用委托包装它以将其传递给 DoStuff.

查看 documentation 以了解有关 局部函数的所有信息

把你的代码通过sharplab.io,我们可以看到代码被降低到:

public class Class
{
    [CompilerGenerated]
    private sealed class <>c__DisplayClass0_0
    {
        public string holder;

        internal void <Caller>b__0(string s)
        {
            this.holder = s;
        }

        internal void <Caller>g__SetHolder1(string s)
        {
            this.holder = s;
        }
    }

    public void Caller()
    {
        Class.<>c__DisplayClass0_0 @object = new Class.<>c__DisplayClass0_0();
        Action<string> setHolder = new Action<string>(@object.<Caller>b__0);
        this.DoStuff(setHolder);
        this.DoStuff(new Action<string>(@object.<Caller>g__SetHolder1));
    }

    public void DoStuff(Action<string> setHolder)
    {
        setHolder("holders new string");
    }
}

因为 actSetHolder 都是 holder 上的闭包,当 Caller 被调用时,一个新的闭包 class 实例被创建并且新的 Action 委托是为 lambda 和本地函数创建的。所以两者的结果代码是相同的。

因此,考虑到您在这里使用它们的方式,它只归结为可读性(正如许多 R# 推荐所做的那样)。局部函数可以说具有更好的语法,因此 R# 建议您以这种方式使用它。