有人能解释一下C#lambda语法吗?

有人能解释一下C#lambda语法吗?,c#,C#,我最近遇到一个静态方法,声明为: public class Foo { public static Func<HtmlHelper, PropertyViewModel, string> Render = (a, b) => { a.RenderPartial(b); return ""; }; } 这样看来,以下内容是等效的: public static string Render(HtmlHelper a, PropertyViewModel

我最近遇到一个静态方法,声明为:

public class Foo
{
  public static Func<HtmlHelper, PropertyViewModel, string> Render = (a, b) =>
  {
    a.RenderPartial(b);
    return "";
  };
}
这样看来,以下内容是等效的:

public static string Render(HtmlHelper a, PropertyViewModel b)
{
  a.RenderPartial(b);
  return "";
}
public static Func<HtmlHelper, PropertyViewModel, string> Render = 
delegate(HtmlHelper a, PropertyViewModel b)
{
    a.RenderPartial(b);
    return "";
};
A) 第一种样式的名称是什么?我意识到它在使用lambdas;是
=
标志把我绊倒了。我无法标记它;)


B) 如果这两个代码块是等效的,那么使用前者比使用后者有什么好处?

好的,为了清楚起见,我将再次写出这两个代码块(并稍微修改该方法,使其更短)

RenderMethod
renderedelegate
之间的区别在于
RenderMethod
是一个方法,而
renderedelegate
是一个委托,或者更具体地说是一个delegate类型的字段。这意味着可以将RenderLegate分配给

什么是代表? 委托是一种类型。从:

委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法相关联

本质上,您可以将委托视为方法的引用/指针,但是委托指向的方法必须与委托期望的签名相匹配。因此,例如
Func
是一个委托,它需要签名为
string MyMethod(HtmlHelper,PropertyViewModel)
的方法,因此我们可以像下面这样将带有该签名的方法分配给该委托:

RenderDelegate = RenderMethod;
"public static Func<HtmlHelper, PropertyViewModel, string> Render = (a, b) => { a.RenderPartial(b); return ""; };"
class-member-declaration ::= field-declaration
field-declaration ::= field-modifiers type variable-declarators ";"

"public static"
field-modifiers ::= field-modifiers field-modifier

"public"
field-modifiers ::= field-modifier
field-modifier ::= "public"

"static"
field-modifier ::= "static"

"Func<HtmlHelper, PropertyViewModel, string>"
type ::= reference-type
reference-type ::= delegate-type
delegate-type ::= type-name
type-name ::= namespace-or-type-name
namespace-or-type-name ::= identifier type-argument-list

"Func"
identifier == "Func"

"<HtmlHelper, PropertyViewModel, string>"
type-argument-list ::= "<" type-arguments ">"

"HtmlHelper, PropertyViewModel, string"
type-arguments ::= type-arguments "," type-argument

"HtmlHelper, PropertyViewModel"
type-arguments ::= type-arguments "," type-argument

"HtmlHelper"
type-arguments ::= type-argument
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "HtmlHelper"

"PropertyViewModel"
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "PropertyViewModel"

"string"
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "string"

"Render = (a, b) => { a.RenderPartial(b); return ""; }"
variable-declarators ::= variable-declarator
variable-declarator ::= identifier "=" variable-initializer  (Here is the equals!)

"Render"
identifier == "Render"

"(a, b) => { a.RenderPartial(b); return ""; }"
variable-initializer ::= expression
expression ::= non-assignment-expression
non-assignment-expression ::= lambda-expression
lambda-expression ::= anonymous-function-signature "=>" anonymous-function-body

"(a, b)"
anonymous-function-signature ::= implicit-anonymous-function-signature
implicit-anonymous-function-signature ::= "(" implicit-anonymous-function-parameter-list ")"

"a, b"
implicit-anonymous-function-parameter-list ::= implicit-anonymous-function-parameter-list "," implicit-anonymous-function-parameter

"a"
implicit-anonymous-function-parameter-list ::= implicit-anonymous-function-parameter
implicit-anonymous-function-parameter == identifier
identifier == "a"

"b"
implicit-anonymous-function-parameter == identifier
identifier == "b"

"{ a.RenderPartial(b); return ""; }"
anonymous-function-body ::= block
block ::= "{" statement-list "}"

"a.RenderPartial(b); return "";"
statement-list ::= statement-list statement

"a.RenderPartial(b);"
statement-list ::= statement
statement ::= embedded-statement
embedded-statement ::= expression-statement
expression-statement ::= statement-expression ";"

"a.RenderPartial(b)"
statement-expression ::= invocation-expression
invocation-expression ::= primary-expression "(" argument-list ")"

"a.RenderPartial"
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= member-access
member-access ::= primary-expression "." identifier

"a"
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= simple-name
simple-name ::= identifier
identifier == "a"

"RenderPartial"
identifier == "RenderPartial"

"b"
argument-list ::= argument
argument ::= expression
expression ::= non-assignment-expression
non-assignment-expression ::= conditional-expression
conditional-expression ::= null-coalescing-expression
null-coalescing-expression ::= conditional-or-expresion
conditional-or-expresion ::= conditional-and-expression
conditional-and-expression ::= inclusive-or-expression
inclusive-or-expression ::= exclusive-or-expression
exclusive-or-expression ::= and-expression
and-expression ::= equality-expression 
equality-expression ::= relational-expression 
relational-expression ::= shift-expression
shift-expression ::= additive-expression 
additive-expression ::= multiplicitive-expression 
multiplicitive-expression ::= unary-expression
unary-expression ::= primary-expression
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= simple-name
simple-name ::= identifier
identifer == "b"

"return "";"
statement ::= embedded-statement
embedded-statement ::= jump-statement
jump-statement ::= return-statement
return-statement ::= "return" expression ";"

""""
expression ::= non-assignment-expression
non-assignment-expression ::= conditional-expression
conditional-expression ::= null-coalescing-expression
null-coalescing-expression ::= conditional-or-expresion
conditional-or-expresion ::= conditional-and-expression
conditional-and-expression ::= inclusive-or-expression
inclusive-or-expression ::= exclusive-or-expression
exclusive-or-expression ::= and-expression
and-expression ::= equality-expression 
equality-expression ::= relational-expression 
relational-expression ::= shift-expression
shift-expression ::= additive-expression 
additive-expression ::= multiplicitive-expression 
multiplicitive-expression ::= unary-expression
unary-expression ::= primary-expression
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= literal
literal ::= string-literal
string-literal == ""
注意Delegate类型(注意大写字母D)和Delegate关键字(小写字母D)之间的差异非常重要。在您的示例中,您使用
Func
generic对象来压缩代码,但是这有点模糊了这里真正发生的事情
Func
是从
Delegate
继承的类型,您可以使用Delegate关键字删除等效类型:

delegate string MyFunction<HtmlHelper helper, PropertyViewModel string>;
static MyFunction RenderDelegate = RenderMethod;
委托字符串MyFunction;
静态MyFunction renderelegate=RenderMethod;
匿名方法 当我们在第一个示例中指定RenderLegate时,我们没有将RenderLegate设置为现有的命名方法,而是在线声明了一个新方法。这称为匿名方法,之所以有效,是因为我们能够将代码块(也使用delegate关键字声明)作为委托参数传递:

匿名函数 回到原始语法——您的示例使用lambda语法以一种有趣的方式删除匿名委托。Lambda表达式是声明短内联方法的好方法,通常在处理列表时使用这些方法,例如,假设我们要按名称对HtmlHelper对象列表进行排序。执行此操作的方法是将比较两个HtmlHelper对象的委托传递给list排序方法,然后排序方法使用该委托对列表中的元素进行比较和排序:

static int MyComparison(HtmlHelper x, HtmlHelper y)
{
    return x.Name.CompareTo(y.Name);
}

static void Main()
{
    List<HtmlHelper> myList = GetList();
    myList.Sort(MyComparison);
}
static int MyComparison(HtmlHelper x,HtmlHelper y)
{
返回x.Name.CompareTo(y.Name);
}
静态void Main()
{
List myList=GetList();
myList.Sort(MyComparison);
}
为了避免短方法的负载分散,可以使用匿名方法在线删除排序方法。关于这一点,真正有用的是,in-line方法可以访问包含范围中声明的变量:

int myInt = 12;
List<HtmlHelper> myList = GetList();
myList.Sort(
    delegate (HtmlHelper x, HtmlHelper y)
    {
        return x.Name.CompareTo(y.Name) - myInt;
    });
int-myInt=12;
List myList=GetList();
myList.排序(
代表(HtmlHelper x、HtmlHelper y)
{
返回x.Name.CompareTo(y.Name)-myInt;
});
然而,这仍然是相当多的输入,因此lambda sytax诞生了,现在你可以这样做:

List<HtmlHelper> myList = GetList();
myList.Sort((x, y) => {return x.Name.CompareTo(y.Name)});
List myList=GetList();
myList.Sort((x,y)=>{return x.Name.CompareTo(y.Name)});
然而,以这种方式声明“正常”方法对我来说似乎毫无意义(而且会让我的眼睛流血)

代表非常有用,是.Net事件系统的基石。多读一些书,把事情弄清楚一点:

A)这种风格就是使用代理。以下是等效的:

public static string Render(HtmlHelper a, PropertyViewModel b)
{
  a.RenderPartial(b);
  return "";
}
public static Func<HtmlHelper, PropertyViewModel, string> Render = 
delegate(HtmlHelper a, PropertyViewModel b)
{
    a.RenderPartial(b);
    return "";
};
公共静态函数呈现=
代表(HtmlHelper a、PropertyViewModel b)
{
a、 第三部分(b);
返回“”;
};
B) 这样做的好处是,您可以将Render视为另一个方法中的变量。然而,在这个特定的实例中,它们或多或少都有相同的优点(尽管后者更容易理解)。

Render是一个函数对象,它以HtmlHelper和PropertyViewModel对象作为参数,并返回一个字符串。是的,它们是等价的


在这种情况下,为什么有人会使用lambda而不是静态函数,我无法理解,但我不知道上下文。我只需要声明一个静态函数,正如您在第二个示例中所做的那样。也许他们认为lambda语法“更酷”,他们自己也忍不住:)。

我认为这种语法的最大优点是,您可以在不扩展类的情况下重新定义方法(只需将字段设置为新方法)


这是个好主意吗?可能不会。但我确信有些地方是有意义的…

在大多数情况下,它们在功能上是等价的。实际上,您可以将普通方法作为变量传递

但也有一些细微的差别,比如能够将函数重新定义为其他函数。如果您使用反射,它可能也不同,例如,它可能不会在类的方法列表中返回。(对反射部分不是100%确定)

下面显示了如何将方法作为变量传递,以及第二种方法如何允许重新定义Func,如果它是普通方法,这是不可能的

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(GetFunc());   //Prints the ToString of a Func<int, string>
        Console.WriteLine(Test(5));     //Prints "test"
        Console.WriteLine(Test2(5));    //Prints "test"
        Test2 = i => "something " + i;
        Console.WriteLine(Test2(5));    //Prints "something 5"
        //Test = i => "something " + i; //Would cause a compile error

    }

    public static string Test(int a)
    {
        return "test";
    }

    public static Func<int, string> Test2 = i =>
    {
        return "test";
    };

    public static Func<int, string> GetFunc()
    {
        return Test;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
Console.WriteLine(GetFunc());//打印Func的ToString
Console.WriteLine(Test(5));//打印“Test”
Console.WriteLine(Test2(5));//打印“test”
Test2=i=>“某物”+i;
"public static Func<HtmlHelper, PropertyViewModel, string> Render = (a, b) => { a.RenderPartial(b); return ""; };"
class-member-declaration ::= field-declaration
field-declaration ::= field-modifiers type variable-declarators ";"

"public static"
field-modifiers ::= field-modifiers field-modifier

"public"
field-modifiers ::= field-modifier
field-modifier ::= "public"

"static"
field-modifier ::= "static"

"Func<HtmlHelper, PropertyViewModel, string>"
type ::= reference-type
reference-type ::= delegate-type
delegate-type ::= type-name
type-name ::= namespace-or-type-name
namespace-or-type-name ::= identifier type-argument-list

"Func"
identifier == "Func"

"<HtmlHelper, PropertyViewModel, string>"
type-argument-list ::= "<" type-arguments ">"

"HtmlHelper, PropertyViewModel, string"
type-arguments ::= type-arguments "," type-argument

"HtmlHelper, PropertyViewModel"
type-arguments ::= type-arguments "," type-argument

"HtmlHelper"
type-arguments ::= type-argument
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "HtmlHelper"

"PropertyViewModel"
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "PropertyViewModel"

"string"
type-argument ::= type
type ::= type-parameter
type-parameter ::= identifier
identifier == "string"

"Render = (a, b) => { a.RenderPartial(b); return ""; }"
variable-declarators ::= variable-declarator
variable-declarator ::= identifier "=" variable-initializer  (Here is the equals!)

"Render"
identifier == "Render"

"(a, b) => { a.RenderPartial(b); return ""; }"
variable-initializer ::= expression
expression ::= non-assignment-expression
non-assignment-expression ::= lambda-expression
lambda-expression ::= anonymous-function-signature "=>" anonymous-function-body

"(a, b)"
anonymous-function-signature ::= implicit-anonymous-function-signature
implicit-anonymous-function-signature ::= "(" implicit-anonymous-function-parameter-list ")"

"a, b"
implicit-anonymous-function-parameter-list ::= implicit-anonymous-function-parameter-list "," implicit-anonymous-function-parameter

"a"
implicit-anonymous-function-parameter-list ::= implicit-anonymous-function-parameter
implicit-anonymous-function-parameter == identifier
identifier == "a"

"b"
implicit-anonymous-function-parameter == identifier
identifier == "b"

"{ a.RenderPartial(b); return ""; }"
anonymous-function-body ::= block
block ::= "{" statement-list "}"

"a.RenderPartial(b); return "";"
statement-list ::= statement-list statement

"a.RenderPartial(b);"
statement-list ::= statement
statement ::= embedded-statement
embedded-statement ::= expression-statement
expression-statement ::= statement-expression ";"

"a.RenderPartial(b)"
statement-expression ::= invocation-expression
invocation-expression ::= primary-expression "(" argument-list ")"

"a.RenderPartial"
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= member-access
member-access ::= primary-expression "." identifier

"a"
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= simple-name
simple-name ::= identifier
identifier == "a"

"RenderPartial"
identifier == "RenderPartial"

"b"
argument-list ::= argument
argument ::= expression
expression ::= non-assignment-expression
non-assignment-expression ::= conditional-expression
conditional-expression ::= null-coalescing-expression
null-coalescing-expression ::= conditional-or-expresion
conditional-or-expresion ::= conditional-and-expression
conditional-and-expression ::= inclusive-or-expression
inclusive-or-expression ::= exclusive-or-expression
exclusive-or-expression ::= and-expression
and-expression ::= equality-expression 
equality-expression ::= relational-expression 
relational-expression ::= shift-expression
shift-expression ::= additive-expression 
additive-expression ::= multiplicitive-expression 
multiplicitive-expression ::= unary-expression
unary-expression ::= primary-expression
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= simple-name
simple-name ::= identifier
identifer == "b"

"return "";"
statement ::= embedded-statement
embedded-statement ::= jump-statement
jump-statement ::= return-statement
return-statement ::= "return" expression ";"

""""
expression ::= non-assignment-expression
non-assignment-expression ::= conditional-expression
conditional-expression ::= null-coalescing-expression
null-coalescing-expression ::= conditional-or-expresion
conditional-or-expresion ::= conditional-and-expression
conditional-and-expression ::= inclusive-or-expression
inclusive-or-expression ::= exclusive-or-expression
exclusive-or-expression ::= and-expression
and-expression ::= equality-expression 
equality-expression ::= relational-expression 
relational-expression ::= shift-expression
shift-expression ::= additive-expression 
additive-expression ::= multiplicitive-expression 
multiplicitive-expression ::= unary-expression
unary-expression ::= primary-expression
primary-expression ::= primary-no-array-creation-expression
primary-no-array-creation-expression ::= literal
literal ::= string-literal
string-literal == ""
int i = 0;
Func<int> Incrementer = () => i++;
Foo.Render = (a, b) =>
{
  var stopWatch = System.Diagnostics.Stopwatch.StartNew();
  a.RenderPartial(b);
  System.Diagnostics.Debug.WriteLine("Rendered " + b.ToString() + " in " + stopWatch.ElapsedMilliseconds);
  return "";
};