繁体   English   中英

将简单的lambda表达式或局部函数分配给委托的性能

[英]Performance of assigning a simple lambda expression or a local function to a delegate

当使用非常简单的表达式作为键来创建带有Enumerable.ToLookup<TSource, TKey> Method (IEnumerable<TSource>, Func<TSource, TKey>)的ILookup时,我可以使用lambda表达式:

var lk = myItems.ToLookup((x) => x.Name);

或局部函数:

var lk = myItems.ToLookup(ByName);

string ByName(MyClass x)
{
     return x.Name;
}

我很好奇在这种简单情况下是否有所不同。

他的回答本地功能VS LAMBDA C#7.0 SO用户svick给出了一个很好的理由,为什么-in中普通的本地函数是最好lambda表达式。

重要的一点是性能上的差异:

创建lambda时,必须创建一个委托,在这种情况下,这是不必要的分配。 本地函数实际上只是函数,不需要委托。

但是,由于我们将其传递给ToLookup()所以无论如何都会创建一个委托。 性能上还是有区别的吗?
我可以想象,编译器必须为myItems.ToLookup的每次调用创建一个新的委托lambda,而本地方法只需要一个委托实例即可。 这是真的?

svick 回答中性能的第二点差异是变量的捕获和闭包的创建:

同样,局部函数在捕获局部变量时效率更高:lambda通常将变量捕获到类中,而局部函数可以使用结构(使用ref传递),这又避免了分配。

但是,由于表达式不使用外部作用域中的变量,因此不必像Reed Copsey 所说的那样使用闭包,也不需要Eric Lippert 扩展 闭包来回答C#闭包中的Lambda表达式吗?

Lambda可以使用闭包来实现,但它本身不一定是闭包。 里德·科普西
[...]
可以视为对象的函数只是一个委托。 使lambda成为闭包的原因是它捕获了其外部变量。 埃里克·利珀特

这多少有些矛盾埃里克利珀自己是他的回答指定的本地函数来代表 埃里克利珀解释一个局部函数为命名的λ:

本地函数基本上只是具有关联名称的lambda。

但这只是在较少的技术细节上,对于确实捕获外部作用域变量的lambda /局部函数的委托。

这个简单的表达式不是递归的,不是通用的,也不是迭代器。 看起来更好的是意见问题。
那么,简单的不捕获,非递归,非泛型和非迭代器Lambda表达式与局部函数之间在性能(或其他方面)上是否存在差异?

使用当前版本的编译器(Roslyn 2.8.0),带有lambda的版本效率更高,因为它可以缓存委托。

查看将两个示例放在不同方法中的代码的IL ,它是有效的:

sealed class HelperClass
{
    public static readonly HelperClass Instance = new HelperClass();

    public static Func<MyClass, string> CachedDelegate;

    internal string LambdaByName(MyClass x)
    {
        return x.Name;
    }

    internal string LocalFunctionByName(MyClass x)
    {
        return x.Name;
    }
}

void Lambda(IEnumerable<MyClass> myItems)
{
    var lk = myItems.ToLookup(HelperClass.CachedDelegate ??
        (HelperClass.CachedDelegate =
            new Func<MyClass, string>(HelperClass.Instance.LambdaByName)));
}

void LocalFunction(IEnumerable<MyClass> myItems)
{
    var lk = myItems.ToLookup(
        new Func<MyClass, string>(HelperClass.Instance.LocalFunctionByName)));
}

请注意, Lambda如何只分配一次委托,然后再使用缓存的委托,而LocalFunction每次都会分配委托。 这使Lambda在这种特定情况下更加有效。

尽管GitHub上一个建议更改编译器以使LocalFunction效率与Lambda

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM