C # lambda, assign local variable vs return data


In C #, a lambda can access a local variable and also return some data.

what is better in the following situation?

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

against

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

I think the performance is different. What's better?



UPDATE (I don't know how to use StackOverflow)

My code is here.

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

But in this case, perhaps 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 definition of the method.

 public static class DatabaseUtility { public static Read<T>( MySqlConnection conn, string query, Func<MySqlDataReader, T> callback); } 
+5
source share
4 answers

Gibbo is right: the return value is clearer, so you should use this and not worry about performance if this code is not in 3% of the code when microoptimizations make sense .

But returning can also be more efficient, because it does not require heap allocation for the closure object and because it means that num is going to be compiled as a local variable and not a closure object field (accessing local variables is cheaper than fields).

Also, if you are going to return a value, there is no reason to declare a variable so early that it will make your code a little shorter:

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

The first is better designed. It is reusable and can be called again and again on various variables (if required).

Performance I'm not sure, most likely negligible.

+2
source

In fact, there is a big semantic difference.

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

Both return 10. The difference is that in the second case, the variable x captured, bound to the body of lamba and can move through contexts.

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 the variable will be when it leaves the context of the function. On the other hand, Execute does not know what will happen to the value passed to the function object via Invoke . This may be useful in some encapsulation contexts. Or perhaps in situations where you push the C # generics restrictions (which is very easy, by the way).

Then you can think in both directions when it comes to your code. for example, "Do I have to handle errors on my side, or am I providing error handling facilities to the user of my interface?"

But then I would prefer to use an abstract class to implement / enforce the above behavior instead of lambdas.

Generally speaking, sending captured variables by context seems to hide the dependencies and makes your code more difficult (in some cases, perhaps even impossible) to read and debug. I think that it should be used only in scenarios where all the other C # tools give either very slow or very ugly code.

+1
source

I want to raise a little problem 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 reverse signature! is it emptiness? If this is not valid, the code you posted will not work:

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

if it is already T, then there is no need to declare Func to pass the Read function.

I think that in this case the return value of the Read function should be T, and given that you want to perform the action with the data type that you are retrieving (in case of some error or for some other case), it would be better to pass the action instead of this:

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

Assume that performance wise should not be a problem unless you are targeting a real-time application (which I think is not your business). However, that would be the best IMHO solution.

hope this helps.

+1
source

Source: https://habr.com/ru/post/1214932/


All Articles