C# 为什么lambda表达式不能使用相同的内部变量?

C# 为什么lambda表达式不能使用相同的内部变量?,c#,C#,我是C#的新手,一直在处理这些lambda值 我的问题是,为什么参数列表中的每个变量都不相同?如果你注意到print(q是变量),square(c是变量)和add(x,y)是变量,IsLessThanTen(f是变量),如果我想让它们都有相同的参数名,比如说Pizza,这可以做到吗。那是我在看的教程。我的第二个小问题是,如果您不只是使用常规函数,那么这将如何使代码变得更好 我认为这些被称为Lambda表达式。我在教程视频中听到了几个不同的名字 问题:同一变量能否用于不同的lambda表达式? 我

我是C#的新手,一直在处理这些lambda值

我的问题是,为什么参数列表中的每个变量都不相同?如果你注意到print(q是变量),square(c是变量)和add(x,y)是变量,IsLessThanTen(f是变量),如果我想让它们都有相同的参数名,比如说Pizza,这可以做到吗。那是我在看的教程。我的第二个小问题是,如果您不只是使用常规函数,那么这将如何使代码变得更好

我认为这些被称为Lambda表达式。我在教程视频中听到了几个不同的名字

问题:同一变量能否用于不同的lambda表达式?

我想知道我是否可以在所有lambda表达式中使用变量索引

  Action<int> print = index => Console.Writeline(index);
Action print=index=>Console.Writeline(索引);
代码:

Action print=q=>Console.WriteLine(q);
Func square=c=>c*c;
Func add=(x,y)=>x+y;
谓词isLessThanTen=f=>f<10;
印刷品(方形(添加(4,5)));
Console.ReadKey();

是的,lambda参数名可以重用,重复的变量名不会“跨越”同级(又称匿名函数)

导致编译器错误

无法在此作用域中声明名为“q”的局部变量 因为它会给已经使用的“q”赋予不同的含义 在“父或当前”范围中表示其他内容


与普通方法相比,lambda表达式有一些很大的好处:

  • Lambdas表达式可能导致-这就是L2S/EF背后的魔力
  • 与普通方法相比,lambda可以充当闭包并捕获自由变量
  • 甜甜的。在LINQ查询中应用上述内容时非常有用

  • 可以在不同的lambda中使用相同的变量名,但它们在包含它们的方法中必须是唯一的。例如:

    void SomeFunction()
    {
        int i;
        Func<int, int> timesTwo = i => i * 2;  // Bad. Conflicts with other variable
    }
    
    void SomeFunction()
    {
    int i;
    Func times2=i=>i*2;//错误。与其他变量冲突
    }
    

    至于你的另一个问题,它们是否比常规方法更好,这完全是主观的,它们都有自己的位置。

    来回答你的第二个问题。这样使用委托的一个好处是,委托所代表的函数可以在运行时更改

    例如,假设您有一个代表
    multiply

    Func<double, double, double> multiply = (a, b) => a * b;
    
    现在,无论你在哪里使用乘法,它实际上都会除法

    在本例中,将
    multiply
    视为一个包含函数的变量,可以作为函数调用。要更改此“变量”的值,必须将其分配给与定义的签名匹配的函数


    我过去在一个解决方案中使用多种类型的数据库时使用过委托。根据数据库是Oracle还是MS SQL,委托会有所不同。

    您可以对所有lambda方法使用相同的变量名

            Action<bool>                 method1 = i => Console.WriteLine(i);
            Func<double, double>         method2 = i => i * i;
            Func<double, double, double> method3 = (i, i2) => i + i2 / i * i *40;
            Predicate<double>            method4 = i => i < 2000;
    
    Action method1=i=>Console.WriteLine(i);
    Func method2=i=>i*i;
    Func方法3=(i,i2)=>i+i2/i*i*40;
    谓词方法4=i=>i<2000;
    
    不能使用名为i的局部变量来进行命名转换。人们之所以使用这些类型的表达式,是因为它们在某些情况下速度更快,并且您可以根据条件动态更改它们

            Action<int>  method1 = i => Console.WriteLine(i + 3);
    
            if (test == 3)
                 method1 = i => Console.WriteLine(i + i);
            else if (test == 2)
                 method1 = i => Console.WriteLine(i + i + i);
            Console.ReadKey();
    
    Action-method1=i=>Console.WriteLine(i+3);
    如果(测试==3)
    method1=i=>Console.WriteLine(i+i);
    否则如果(测试==2)
    method1=i=>Console.WriteLine(i+i+i);
    Console.ReadKey();
    

    如上所述,method1已在上面定义,但根据测试结果,method1可以更改为其他内容。如果你愿意,你可以用两种不同的方法做同样的事情。我有时不确定人们是否应该使用这种例子。我曾多次在代码中看到过它,但坦率地说,决定何时使用它对我来说似乎很奇怪,因为您可以像上面的示例一样在代码中使用ever函数。

    我不理解这个问题。您是在问是否可以在单独的lambda表达式中重用相同的变量(当然在同一个闭包之外),还是在同一个表达式中使用它?你能提供一个你认为应该工作但不工作的例子吗?当然,如果每个参数在概念上代表相同的东西,那么使用相同的参数名就可以了。它使用相同的参数名来表示完全不同的东西,这是一个问题。@Servy非常好。我引用了你的评论。根据我的测试,lambda也比函数调用快,我支持,因为它们已经快了delegates@Gusman假与假。lambda不是代理。它们是用于创建委托实例的一种可能语法。lambda将被编译成命名方法,就像任何其他命名方法一样;在编译代码之前,该名称根本不为人所知。您不知道该名称是什么,但该方法在运行时实际上会有一个名称。您的测试在某些方面存在缺陷的可能性非常高;要么你没有比较等价的操作,要么你没有正确地测量它们。这两种方法都很容易做到,因为基准测试很难做到。不,测试了很多次,因为我期望得到oposite结果,调用lambda函数(或函数的委托)更快。我对“are delegate”的意思是,您将从一个委托中使用它(当您将它指定给一个变量,并创建一个委托时),您不能像调用纯函数一样调用它。@Gusman说您已经测试过它,这毫无意义。正如我所说,对代码进行基准测试很难,实际上没有人能正确地进行。你几乎肯定不是在比较你的想法
    Func<double, double, double> multiply = (a, b) => a * b;
    
    if(crazyDemandIsMet){
       multiply = (a, b) => a / b;
    }
    
            Action<bool>                 method1 = i => Console.WriteLine(i);
            Func<double, double>         method2 = i => i * i;
            Func<double, double, double> method3 = (i, i2) => i + i2 / i * i *40;
            Predicate<double>            method4 = i => i < 2000;
    
            Action<int>  method1 = i => Console.WriteLine(i + 3);
    
            if (test == 3)
                 method1 = i => Console.WriteLine(i + i);
            else if (test == 2)
                 method1 = i => Console.WriteLine(i + i + i);
            Console.ReadKey();