[英]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
變量。 但這沒關系,因為您不會更改x
或y
的值。
您需要一個描述函數類型的委托。 您可以構建自己的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;
};
}
}
正如其他答案正確指出的那樣:
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.