簡體   English   中英

C#lambda,分配局部變量vs返回數據

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


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

Gibbo是對的:返回值更清楚,所以你應該使用它而不用擔心性能,除非當微優化有意義時這個代碼在3%的代碼中

但是返回也可以更高效,因為它不需要為閉包對象分配堆,因為它意味着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#的泛型限制的情況下(順便說一下這很容易)。

然后,您可以在涉及代碼時考慮兩種方式。 例如“我是否想要處理我身邊的錯誤,或者我是否為我的界面用戶提供了錯誤處理方法?”

但是,我寧願使用抽象類來實現/強制執行上述行為而不是lambdas。

一般來說,在上下文中發送捕獲的變量似乎隱藏了依賴性,並使您的代碼更難(在某些情況下甚至可能無法)進行讀取和調試。 我認為它應該僅用於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);
}

除非你的目標是實時應用程序(我認為這不是你的情況),否則性能明智的前提應該不是問題。 然而,那將是更整潔的解決方案恕我直言。

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM