簡體   English   中英

由於我不能在 C# 中使用帶有隱式變量的 lambda 函數,我可以在這里替換什么?

[英]What can I replace here since I can't have a lambda function with implicit variable in C#?

我正在嘗試從這個 C++ 代碼到 C# 為 2D 游戲演示實現一個基於磁貼的平台系統,

這就是我所寫的,但由於使用了 var 變量,它無法編譯。

 class GameLogic
{
    // Level storage
    String sLevel;
    int nLevelWidth;
    int nLevelHeight;

    // Player Properties
    float fPlayerPosX = 1.0f;
    float fPlayerPosY = 1.0f;
    float fPlayerVelX = 0.0f;
    float fPlayerVelY = 0.0f;
    bool bPlayerOnGround = false;

    // Camera properties
    float fCameraPosX = 0.0f;
    float fCameraPosY = 0.0f;

    public GameLogic()
    {
         var GetTile = (ref int x, ref int y) =>
        {
            if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
                return sLevel[y * nLevelWidth + x];
            else
                return "";
        };

        var SetTile = (ref int x, ref int y, string c)=>                
        {
            if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
                sLevel[y * nLevelWidth + x] = c;
        };

    }
}

你建議我在這里做什么,來實現這個功能。 感謝您的時間。

由於var語句,它無法編譯。 當您使用LambdaExpressions並且想要將其保存到變量時,您必須定義delegate類型。 但是你不能在這里使用ref變量。 但這沒關系,因為您不會更改xy的值。

您需要一個描述函數類型的委托。 您可以構建自己的delegate類型,但在 C# 中,有兩種內置類型可用於這種情況。
Action & Action<T1-16> -> 總是返回void
Func<T1-17>可以定義返回類型

GetTile函數接受兩個int並返回一個string
所以你可以使用Func<int, int, string>
SetTitle函數多了一個string參數,但沒有返回類型。
那將是Action<int, int, string>

internal class GameObject
{
    private int nLevelWidth;
    private int nLevelHeight;

    public GameLogic()
    {
        Func<int, int, string> GetTile = (int x, int y) =>
        {
            if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
                return sLevel[y * nLevelWidth + x];
            else
                return "";
        };

        Action<int, int, string> SetTile = (int x, int y, string c)=>                
        {
            if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
                sLevel[y * nLevelWidth + x] = c;
        };
    }
}

這是一篇關於代表的好文章。

正如其他答案正確指出的那樣:

  • 不能在 C# 中將var與 lambda 一起使用,因為類型不明確。 您必須明確說明委托類型。
  • 您對ref使用表明您誤解了外部變量捕獲在 C++ 和 C# 中的工作方式。 您不需要制作這些ref ,外部變量將被自動捕獲。

然而,到目前為止給出的答案都沒有告訴你這個問題的更好解決方案,那就是根本不使用 lambdas! 只需使用本地函數。

public GameLogic()
{
    ... other code here ...
    string GetTile(int x, int y)
    {
        if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
            return sLevel[y * nLevelWidth + x];
        else
            return "";
    }

不需要 lambda。

請注意,此解決方案需要 C# 7.0 或更高版本。

(更好的解決方案是將所有這些代碼放入一個類中;制作一個自定義數據類型來為您工作。但是您特別詢問了如何直接移植此代碼,而不是如何重構它。)

Lambda 表達式沒有編譯時類型,但可以轉換為任何匹配的委托或表達式類型。 這就是為什么根據 MSDN lambda 表達式不能隱式輸入的原因(另請查看Eric Lippert 的這個答案

所以:

Func<int, int, string> GetTile = (int x, int y) =>
{
    if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
        return sLevel[y * nLevelWidth + x];
    else
        return "";
};

Action<int, int, string> SetTile = (int x, int y, string c)=>                
{
   if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
       sLevel[y * nLevelWidth + x] = c;
};

您可以像下面這樣聲明兩個delegates

delegate void ActionRef(ref int x, ref int y, string c);
delegate string FuncRef(ref int x, ref int y);

而不是使用var ,您可以將這些delegates作為函數類型。

public GameLogic()
{
    FuncRef GetTile = (ref int x, ref int y) =>
    {
        if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
            return sLevel[y * nLevelWidth + x];
        else
            return "";
    };

    ActionRef SetTile = (ref int x, ref int y, string c) =>
    {
        if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
            sLevel[y * nLevelWidth + x] = c;
    };
}

暫無
暫無

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

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