为什么要将 lambda 表达式分配给私有字段?
Why assign lambda expression to private field?
我在工作中查看了一些代码,发现了一些我不熟悉的东西。
此处已满属性我熟悉:
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
但后来我看到了(我记不清了)这个:
private int myVar = x => x.Something;
这是在使用 CSLA 的应用程序中发现的。
将 lambda 表达式用作变量(public 或私有)就像使用可以更改的函数。
例如我可以做这样的事情
var myFavoriteFunction = (x) => x.FirstFunction();
//do some work
myFavoriteFunction(someobject)
//now change the function
myFavoriteFunction = (x) => x.SecondFunction();
myFavoriteFunction(someobject)
在不知道您正在查看的代码的情况下,您可能会认为这是一个点击处理程序,点击按钮时正在执行的功能可能会发生变化。 (当然,您也可以使用不同的点击处理程序,但这不是重点)
以这种方式使用表达式也称为 属性 选择器.
正确的语法实际上是这样的。
private Expression<Func<Foo, int>> myVar = x => x.Something;
这些有无数的用途,一个典型的例子是避免必须 "hard-code" 成员名称,否则必须将其键入为字符串文字(编译器仍未检查并证明难以重构)。
下面是这个例子的一个实际应用。
Implementing INotifyPropertyChanged - does a better way exist?
您还看到它在 Fluent interface implementations, such as Fluent NHibernate 中被大量使用。
然而,随着 C# 6 中 nameof()
表达式的出现,我们很快就会看到这种技术逐渐消失。
您看到的与 属性 无关,它是委托分配。 (类型可能不是 int)
Func<int,int> doubleMyNumber = (i) => 2 * i;
这就像一个委托,写成一个匿名函数。更多信息在这里:https://msdn.microsoft.com/fr-fr/library/bb397687.aspx
在 C# 6 中,您将能够看到像这样更奇怪的符号
public int AgeInDogYears() => Age * 7;
您将能够将方法的主体编写为 lambda 表达式。 http://csharp.2000things.com/2014/11/03/1217-using-lambda-expressions-for-function-members/
Biscuits 写了关于 属性(或字段)选择器...这些有两种用途:一种(他所说的)获得 field/property 的名称。
怎么做?
鉴于:
Expression<Func<Foo, int>> expression = x => x.Something;
你做到了:
string name = ((MemberExpression)expression.Body).Member.Name;
正如其他人所写,在 C# 6.0 中,由于 nameof()
(通常速度更快,因为它是在编译时而不是在运行时完成的),在 C# 6.0 中这将变得几乎无用,而在 C# 5.0 中部分无用,这要归功于[CallerMemberName]
.
第二个用途是,通过将 Expression<>
传递给方法,即 "getter"(给对象 returns 某物的值的函数),该方法可以 "build" 一个 "setter".
Func<Foo, int> getter = expression.Compile();
var parameter = Expression.Parameter(expression.ReturnType);
Action<Foo, int> setter = Expression.Lambda<Action<Foo, int>>(
Expression.Assign(expression.Body, parameter ),
new[] { expression.Parameters[0], parameter }).Compile();
Foo foo = new Foo();
setter(foo, 5); // Example of use of the setter
int value = getter(foo); // Example of use of the getter
如果你必须使用一次 setter,这比直接使用反射要慢得多(因为 Expression
s 必须构建,然后编译等等,并且在Expression
的构建和编译(但不在使用中)有反射的使用)。但是如果你需要多次使用 getter/setter,那么它会变得更快(如果你 "cache" 它们),因为使用这种方式构建的 getter/setter 几乎和直接访问 property/field(较慢的部分是创建 getter/setter)
我在工作中查看了一些代码,发现了一些我不熟悉的东西。
此处已满属性我熟悉:
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
但后来我看到了(我记不清了)这个:
private int myVar = x => x.Something;
这是在使用 CSLA 的应用程序中发现的。
将 lambda 表达式用作变量(public 或私有)就像使用可以更改的函数。
例如我可以做这样的事情
var myFavoriteFunction = (x) => x.FirstFunction();
//do some work
myFavoriteFunction(someobject)
//now change the function
myFavoriteFunction = (x) => x.SecondFunction();
myFavoriteFunction(someobject)
在不知道您正在查看的代码的情况下,您可能会认为这是一个点击处理程序,点击按钮时正在执行的功能可能会发生变化。 (当然,您也可以使用不同的点击处理程序,但这不是重点)
以这种方式使用表达式也称为 属性 选择器.
正确的语法实际上是这样的。
private Expression<Func<Foo, int>> myVar = x => x.Something;
这些有无数的用途,一个典型的例子是避免必须 "hard-code" 成员名称,否则必须将其键入为字符串文字(编译器仍未检查并证明难以重构)。
下面是这个例子的一个实际应用。
Implementing INotifyPropertyChanged - does a better way exist?
您还看到它在 Fluent interface implementations, such as Fluent NHibernate 中被大量使用。
然而,随着 C# 6 中 nameof()
表达式的出现,我们很快就会看到这种技术逐渐消失。
您看到的与 属性 无关,它是委托分配。 (类型可能不是 int)
Func<int,int> doubleMyNumber = (i) => 2 * i;
这就像一个委托,写成一个匿名函数。更多信息在这里:https://msdn.microsoft.com/fr-fr/library/bb397687.aspx
在 C# 6 中,您将能够看到像这样更奇怪的符号
public int AgeInDogYears() => Age * 7;
您将能够将方法的主体编写为 lambda 表达式。 http://csharp.2000things.com/2014/11/03/1217-using-lambda-expressions-for-function-members/
Biscuits 写了关于 属性(或字段)选择器...这些有两种用途:一种(他所说的)获得 field/property 的名称。
怎么做?
鉴于:
Expression<Func<Foo, int>> expression = x => x.Something;
你做到了:
string name = ((MemberExpression)expression.Body).Member.Name;
正如其他人所写,在 C# 6.0 中,由于 nameof()
(通常速度更快,因为它是在编译时而不是在运行时完成的),在 C# 6.0 中这将变得几乎无用,而在 C# 5.0 中部分无用,这要归功于[CallerMemberName]
.
第二个用途是,通过将 Expression<>
传递给方法,即 "getter"(给对象 returns 某物的值的函数),该方法可以 "build" 一个 "setter".
Func<Foo, int> getter = expression.Compile();
var parameter = Expression.Parameter(expression.ReturnType);
Action<Foo, int> setter = Expression.Lambda<Action<Foo, int>>(
Expression.Assign(expression.Body, parameter ),
new[] { expression.Parameters[0], parameter }).Compile();
Foo foo = new Foo();
setter(foo, 5); // Example of use of the setter
int value = getter(foo); // Example of use of the getter
如果你必须使用一次 setter,这比直接使用反射要慢得多(因为 Expression
s 必须构建,然后编译等等,并且在Expression
的构建和编译(但不在使用中)有反射的使用)。但是如果你需要多次使用 getter/setter,那么它会变得更快(如果你 "cache" 它们),因为使用这种方式构建的 getter/setter 几乎和直接访问 property/field(较慢的部分是创建 getter/setter)