在C#中,lambda可以访问局部变量,也可以返回一些数据。
然后,哪种情况更好?
int num;
Func<int> func = ()=>{return 10;}
num = func();
VS
int num;
Action action = ()=>{num = 10;}
我认为,表现不同。
哪个更好?
更新(我不知道如何使用StackOverflow)
我的代码在这里。
ErrorCode errorCode;
errorCode = DatabaseUtility.Read<ErrorCode>(
conn,
DatabaseUtility.CreateSelectQuery(....),
reader =>
{
if(reader.Read())
return ErrorCode.None;
return ErrorCode.InvalidParam;
});
但在这种情况下,我可以这样做。
ErrorCode errorCode;
DatabaseUtility.Read(
conn,
DatabaseUtility.CreateSelectQuery(....),
reader =>
{
if(reader.Read())
errorCode = ErrorCode.None;
else
errorCode = ErrorCode.InvalidParam;
});
而且,这是方法定义。
public static class DatabaseUtility
{
public static Read<T>(
MySqlConnection conn,
string query,
Func<MySqlDataReader, T> callback);
}
答案 0 :(得分:4)
Gibbo是对的:返回值更清楚,所以你应该使用它而不用担心性能,除非这段代码在the 3% of code when microoptimizations make sense中。
但是返回也可以更高效,因为它不需要为闭包对象分配堆,因为它意味着num
将被编译为局部变量,而不是闭包对象(访问局部变量比字段便宜)。
另外,如果您要返回该值,则没有理由这么早地声明变量,这会使您的代码稍微缩短:
Func<int> func = ()=>{return 10;}
int num = func();
答案 1 :(得分:2)
第一个设计得更好。它是可重用的,可以在不同的变量上反复调用(如果需要)。
表现我不确定,很可能是微不足道的。
答案 2 :(得分:1)
实际上存在很大的语义差异。
() => 10;
() => x = 10;
两者都返回10.不同之处在于,在第二种情况下,x
变量被捕获,绑定到lamba体,并且可以通过上下文传播。
想象:
void SomeFunction()
{
int variable;
Execute((a) => variable = a);
}
void Execute(Action<int> statement)
{
statement.Invoke(7);
}
这里SomeFunc
在退出函数上下文时不知道变量的值是什么。另一方面,Execute
不知道通过Invoke
传递给函数对象的值会发生什么。这在某些封装上下文中可能很有用。或者可能在你达到C#的泛型限制的情况下(顺便说一下这很容易)。
然后,您可以在涉及代码时考虑两种方式。例如&#34;我是否想要处理我方面的错误,或者我是否为我的界面用户提供了错误处理方法?&#34;
但是,我宁愿使用抽象类来实现/强制执行上述行为而不是lambdas。
一般来说,在上下文中发送捕获的变量似乎会隐藏依赖关系并使您的代码更难(在某些情况下甚至可能无法)进行读取和调试。我认为它应该只用在C#的所有其他方法产生非常慢或非常丑陋的代码的场景中。
答案 3 :(得分:1)
我想用您发布的代码提出一个小问题:
public static class DatabaseUtility
{
public static Read<T>(
MySqlConnection conn,
string query,
Func<MySqlDataReader, T> callback);
}
该方法没有返回类型签名!它无效吗? 如果它无效,您发布的代码将无效:
ErrorCode errorCode;
errorCode = DatabaseUtility.Read<ErrorCode>(
conn,
DatabaseUtility.CreateSelectQuery(....),
reader =>
{
if(reader.Read())
return ErrorCode.None;
return ErrorCode.InvalidParam;
});
如果它已经是T那么就没有必要声明一个Func传递给函数Read。
我认为在这种情况下,函数Read的返回值应为T,并且假设您要使用要检索的数据类型执行操作(如果出现某些错误或某些其他情况),则会更好反过来传递一个动作:
public static class DatabaseUtility
{
public static T Read<T>(
MySqlConnection conn,
string query,
Action<MySqlDataReader> callback);
}
前提是性能明智不应该是一个问题,除非你的目标是实时应用程序(我认为这不是你的情况)。然而,这将是更整洁的解决方案恕我直言。
希望它有所帮助。