简体   繁体   English

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

[英]C# lambda, assign local variable vs return data


In C#, lambda can access local variable, and also return some data. 在C#中,lambda可以访问局部变量,也可以返回一些数据。

then, which is better in following situation? 那么,哪种情况更好呢?

int num;
Func<int> func = ()=>{return 10;}
num = func();

vs VS

int num;
Action action = ()=>{num = 10;}

I think, the performance is different. 我认为,表现是不同的。 Which is better? 哪个更好?



UPDATE(I dont know how to use StackOverflow) 更新(我不知道如何使用StackOverflow)

My code here. 我的代码在这里。

ErrorCode errorCode;
errorCode = DatabaseUtility.Read<ErrorCode>(
    conn,
    DatabaseUtility.CreateSelectQuery(....),
    reader =>
    {
        if(reader.Read())
            return ErrorCode.None;

        return ErrorCode.InvalidParam;
    });

But in this case, may be I can do like this. 但在这种情况下,我可以这样做。

ErrorCode errorCode;
DatabaseUtility.Read(
    conn,
    DatabaseUtility.CreateSelectQuery(....),
    reader =>
    {
        if(reader.Read())
            errorCode = ErrorCode.None;
        else
            errorCode = ErrorCode.InvalidParam;
    });

And, this is the method definition. 而且,这是方法定义。

public static class DatabaseUtility
{
    public static Read<T>(
        MySqlConnection conn,
        string query,
        Func<MySqlDataReader, T> callback);
}

Gibbo is right: returning the value is clearer, so you should use that and not worry about performance, unless this code is in the 3% of code when microoptimizations make sense . Gibbo是对的:返回值更清楚,所以你应该使用它而不用担心性能,除非当微优化有意义时这个代码在3%的代码中

But returning the can also be more efficient, because it doesn't require heap allocation for the closure object and because it means num is going to be compiled as a local variable, not a field on the closure object (accessing local variables is cheaper than fields). 但是返回也可以更高效,因为它不需要为闭包对象分配堆,因为它意味着num将被编译为局部变量,而不是闭包对象上的字段(访问局部变量比字段)。

Also, if you're going to return the value, there is no reason to declare the variable so early, which will make your code slightly shorter: 此外,如果您要返回该值,则没有理由这么早地声明变量,这会使您的代码稍微缩短:

Func<int> func = ()=>{return 10;}
int num = func();

The first one is better designed. 第一个是更好的设计。 It is reusable and can be called again and again on different variables (if required). 它是可重用的,可以在不同的变量上反复调用(如果需要)。

Performance I am not sure of, most likely negligible. 性能我不确定,很可能是微不足道的。

Actually there is a big semantical difference. 实际上有一个很大的语义差异。

() => 10;
() => x = 10;

Both return 10. The difference is that in second case, the x variable is captured, bound to the lamba body, and can travel through contexts. 两者都返回10.不同之处在于,在第二种情况下, x变量被捕获,绑定到lamba体,并且可以穿过上下文。

Imagine: 想像:

void SomeFunction()
{
    int variable;
    Execute((a) => variable = a);
}

void Execute(Action<int> statement)
{
    statement.Invoke(7);
}

Here SomeFunc has no idea what the value of variable will be when exiting the function context. 这里SomeFunc不知道退出函数上下文时变量的值是什么。 On the other hand the Execute has no idea what will happen with the value passed into the function object through Invoke . 另一方面, Execute不知道通过Invoke传递给函数对象的值会发生什么。 This could be useful in some encapsulation contexts. 这在某些封装上下文中可能很有用。 Or possibly in situations where you hit C#'s generics limits (which is very easy by the way). 或者可能在你遇到C#的泛型限制的情况下(顺便说一下这很容易)。

You can then think both ways when it comes to your code. 然后,您可以在涉及代码时考虑两种方式。 eg "Do I want to handle the errors on my side, or do I provide the user of my interface with means of error handling?" 例如“我是否想要处理我身边的错误,或者我是否为我的界面用户提供了错误处理方法?”

But then, I'd rather use abstract class to implement/enforce the aforementioned behaviour instead of lambdas. 但是,我宁愿使用抽象类来实现/强制执行上述行为而不是lambdas。

Generally speaking, sending captured variables over contexts seems to hide dependencies and makes your code harder (in some cases maybe even impossible) to read and debug. 一般来说,在上下文中发送捕获的变量似乎隐藏了依赖性,并使您的代码更难(在某些情况下甚至可能无法)进行读取和调试。 I think it should only be used in scenarios where all other means of C# either yield very slow or very ugly code. 我认为它应该仅用于C#的所有其他方法产生非常慢或非常难看的代码的情况。

I want to raise a small issue with the code you posted: 我想用您发布的代码提出一个小问题:

public static class DatabaseUtility
{
    public static Read<T>(
        MySqlConnection conn,
        string query,
        Func<MySqlDataReader, T> callback);
}

the method has no return type signature! 该方法没有返回类型签名! is it void? 它无效吗? If it is void the code you posted won't work: 如果它无效,您发布的代码将无效:

ErrorCode errorCode;
errorCode = DatabaseUtility.Read<ErrorCode>(
    conn,
    DatabaseUtility.CreateSelectQuery(....),
    reader =>
    {
        if(reader.Read())
            return ErrorCode.None;

        return ErrorCode.InvalidParam;
    });

if it is T already then there is no need to declare a Func to pass to the function Read. 如果它已经是T那么就没有必要声明一个Func传递给函数Read。

I think in this very case return value of the function Read should be T, and given that you want to perform an action with the datatype you are retrieving (in case of some error or for some other case) it would be better off to pass an action instead: 我认为在这种情况下,函数Read的返回值应为T,并且假设您要使用要检索的数据类型执行操作(如果出现某些错误或某些其他情况),最好通过一个动作:

public static class DatabaseUtility
{
    public static T Read<T>(
        MySqlConnection conn,
        string query,
        Action<MySqlDataReader> callback);
}

Premise that performance wise it should not be a problem unless you are targeting a real time application (which I think it's not your case). 除非你的目标是实时应用程序(我认为这不是你的情况),否则性能明智的前提应该不是问题。 However that would be the neater solution IMHO. 然而,那将是更整洁的解决方案恕我直言。

hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM