有人能解释一下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事件系统的基石。多读一些书,把事情弄清楚一点:
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 "";
};