C# lambda,赋值局部变量与返回数据
本文关键字:返回 数据 局部变量 赋值 lambda | 更新日期: 2024-11-07 03:52:08
在 C# 中,lambda 可以访问局部变量,也可以返回一些数据。
那么,在以下情况下哪个更好?
int num;
Func<int> func = ()=>{return 10;}
num = func();
与
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);
}
Gibbo 是对的:返回值更清晰,所以你应该使用它而不必担心性能,除非当微优化有意义时,这段代码在 3% 的代码中。
但是返回 the 也可以更有效,因为它不需要为闭包对象分配堆,并且因为这意味着num
将被编译为局部变量,而不是闭包对象上的字段(访问局部变量比字段便宜)。
此外,如果你要返回值,没有理由这么早声明变量,这将使你的代码稍微短一些:
Func<int> func = ()=>{return 10;}
int num = func();
第一个设计得更好。它是可重用的,可以在不同的变量上一次又一次地调用(如果需要)。
性能我不确定,很可能可以忽略不计。
实际上有很大的语义差异。
() => 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# 泛型限制的情况下(顺便说一下,这很容易)。
然后,当涉及到你的代码时,你可以同时考虑这两种方式,例如,"我是否要处理我这边的错误,或者我是否为我的界面的用户提供错误处理方法?
但是,我宁愿使用抽象类来实现/执行上述行为,而不是lambda。
一般来说,通过上下文发送捕获的变量似乎隐藏了依赖项,并使代码更难(在某些情况下甚至可能不可能)阅读和调试。我认为它应该只在所有其他 C# 方法产生非常慢或非常丑陋的代码的情况下使用。
对您发布的代码提出一个小问题:
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);
}
前提是性能明智,除非您针对实时应用程序(我认为这不是您的情况),否则它应该不是问题。但是,恕我直言,这将是更整洁的解决方案。
希望对您有所帮助。