C#lambda,分配局部变量vs返回数据

时间:2015-03-08 14:07:51

标签: c# lambda


在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);
}

4 个答案:

答案 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);
}

前提是性能明智不应该是一个问题,除非你的目标是实时应用程序(我认为这不是你的情况)。然而,这将是更整洁的解决方案恕我直言。

希望它有所帮助。