谓词和 lambda 表达式

发布于 2024-07-29 19:10:33 字数 108 浏览 4 评论 0原文

我最近转移到.net 3.0(Windows 窗体,C#)。 我想了解更多关于谓词和 lambda 表达式的信息。 我们应该在哪里使用它们? 它们会提高性能吗? 以及它们内部如何运作。 谢谢。

I have recently moved to .net 3.0 (windows forms, C#). I want to know more about predicates and lambda expressions. Where should we use them? Do they improve performance? and how do they work internally. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

茶花眉 2024-08-05 19:10:33

如果你搜索 Stack Overflow,你会发现大约一千个答案来解释它们的用途。 简而言之,lambda 是一种在您想要将匿名方法传递给另一个方法时编写匿名方法的方法。 从技术上讲,与匿名方法的delegate 语法相同,但增加了类型推断的功能,因此您无需声明参数类型。 谓词是一种接受某些值并返回 bool 的方法 - 例如 Where 的参数。

不引用任何外部变量的 lambda 会变成具有虚构名称的私有静态方法。 如果它引用封闭类的实例成员,它就成为实例方法。 如果它引用局部变量,这些变量将被“提升”为编译器生成的类的字段,该类是在封闭方法开始运行时分配的,并且 lambda 的主体成为该新类中的方法。

至于性能,它们并没有太大区别。 它们涉及临时对象的创建,但是 我发现 GC 收集这些数据的效率非常高

If you search Stack Overflow you'll find about a thousand answers explaining what they're for. In short - a lambda is a way of writing an anonymous method at the point where you want to pass it to another method. Technically the same as the delegate syntax for an anonymous method, although with added powers of type inference so you don't need to state the parameter types. A predicate is a method that accepts some value and returns a bool - an example would be the argument to Where.

A lambda that doesn't refer to any external variables gets turned into a private static method with a made-up name. If it refers to instance members of the enclosing class, it becomes an instance method. If it refers to local variables, those variables get "hoisted" into being fields of a compiler-generated class that is allocated when the enclosing method starts running, and the lambda's body becomes a method in that new class.

As for performance, they don't make that much difference. They involve the creation of temporary objects, but I find that these are collected extremely efficiently by the GC.

始终不够爱げ你 2024-08-05 19:10:33

如果您想研究 C# 的不同版本以及它们有何不同。我的建议是阅读 jon skeet 的《C.Sharp.in.Depth》一书。 这将使您更好地了解新版本

If you want to study the different versions of C# and how they different .My suggestion is read the book C.Sharp.in.Depth by jon skeet . This will give you the better understanding of new versions

七秒鱼° 2024-08-05 19:10:33

它们会提高性能吗? 如何
他们在内部工作吗? 谢谢。

大多数情况下,您永远不会注意到性能受到影响。 然而,有一些病态的情况会影响性能,即过度使用定点组合器

这是一个众所周知的技巧,我们可以使用 Y-combinator 来编写递归 lambda 函数,但是请考虑以下代码:

using System;
using System.Diagnostics;

namespace YCombinator
{
    class Program
    {
        static Func<T, U> y<T, U>(Func<Func<T, U>, Func<T, U>> f)
        {
            return f(x => y<T, U>(f)(x));
        }

        static int fibIter(int n)
        {
            int fib0 = 0, fib1 = 1;
            for (int i = 1; i <= n; i++)
            {
                int tmp = fib0;
                fib0 = fib1;
                fib1 = tmp + fib1;
            }
            return fib0;
        }

        static Func<int, int> fibCombinator()
        {
            return y<int, int>(f => n =>
            {
                switch (n)
                {
                    case 0: return 0;
                    case 1: return 1;
                    default: return f(n - 1) + f(n - 2);
                }
            });
        }

        static int fibRecursive(int n)
        {
            switch (n)
            {
                case 0: return 0;
                case 1: return 1;
                default: return fibRecursive(n - 1) + fibRecursive(n - 2);
            }
        }

        static void Benchmark(string msg, int iterations, Func<int, int> f)
        {
            int[] testCases = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20 };
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i <= iterations; i++)
            {
                foreach (int n in testCases)
                {
                    f(n);
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}", msg, watch.Elapsed.TotalMilliseconds);
        }

        static void Main(string[] args)
        {
            int iterations = 10000;
            Benchmark("fibIter", iterations, fibIter);
            Benchmark("fibCombinator", iterations, fibCombinator());
            Benchmark("fibRecursive", iterations, fibRecursive);
            Console.ReadKey(true);
        }
    }
}

该程序打印出:

fibIter: 14.8074
fibCombinator: 61775.1485
fibRecursive: 2591.2444

fibCombinator 和 fibRecursive 在功能上等效并且具有相同的计算复杂度,但 fibCombinator 是完整的 4100x由于所有中间对象分配,速度较慢。

Do they improve performance? and how
do they work internally. Thanks.

For the most part, you'll never notice the performance hit. However, there are some pathological cases which will kill performance, namely overzealous use of fixed point combinators.

Its a well-known trick that we can use the Y-combinator to write recursive lambda functions, however consider the following code:

using System;
using System.Diagnostics;

namespace YCombinator
{
    class Program
    {
        static Func<T, U> y<T, U>(Func<Func<T, U>, Func<T, U>> f)
        {
            return f(x => y<T, U>(f)(x));
        }

        static int fibIter(int n)
        {
            int fib0 = 0, fib1 = 1;
            for (int i = 1; i <= n; i++)
            {
                int tmp = fib0;
                fib0 = fib1;
                fib1 = tmp + fib1;
            }
            return fib0;
        }

        static Func<int, int> fibCombinator()
        {
            return y<int, int>(f => n =>
            {
                switch (n)
                {
                    case 0: return 0;
                    case 1: return 1;
                    default: return f(n - 1) + f(n - 2);
                }
            });
        }

        static int fibRecursive(int n)
        {
            switch (n)
            {
                case 0: return 0;
                case 1: return 1;
                default: return fibRecursive(n - 1) + fibRecursive(n - 2);
            }
        }

        static void Benchmark(string msg, int iterations, Func<int, int> f)
        {
            int[] testCases = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20 };
            Stopwatch watch = Stopwatch.StartNew();
            for (int i = 0; i <= iterations; i++)
            {
                foreach (int n in testCases)
                {
                    f(n);
                }
            }
            watch.Stop();
            Console.WriteLine("{0}: {1}", msg, watch.Elapsed.TotalMilliseconds);
        }

        static void Main(string[] args)
        {
            int iterations = 10000;
            Benchmark("fibIter", iterations, fibIter);
            Benchmark("fibCombinator", iterations, fibCombinator());
            Benchmark("fibRecursive", iterations, fibRecursive);
            Console.ReadKey(true);
        }
    }
}

This program prints out:

fibIter: 14.8074
fibCombinator: 61775.1485
fibRecursive: 2591.2444

fibCombinator and fibRecursive are functionally equivalent and have the same computational complexity, but fibCombinator is a full 4100x slower due to all of the intermediate object allocations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文