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

C# lambda,赋值局部变量与返回数据

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

前提是性能明智,除非您针对实时应用程序(我认为这不是您的情况),否则它应该不是问题。但是,恕我直言,这将是更整洁的解决方案。

希望对您有所帮助。