C# 导致StackOverflowException的字典上的Foreach循环
我的错误是 StackOverflowException Board.GetSquare(UnityEngine.Vector2 currentPos)(位于Assets/Scripts/Board/Board.cs:111) 堆栈跟踪为C# 导致StackOverflowException的字典上的Foreach循环,c#,dictionary,unity3d,stack-overflow,C#,Dictionary,Unity3d,Stack Overflow,我的错误是 StackOverflowException Board.GetSquare(UnityEngine.Vector2 currentPos)(位于Assets/Scripts/Board/Board.cs:111) 堆栈跟踪为 Board.GetSquare(UnityEngine.Vector2 currentPos)(在 资产/脚本/Board/Board.cs:111) Board.GetSquare(UnityEngine.Vector2 currentPos)(位于 资产/
Board.GetSquare(UnityEngine.Vector2 currentPos)(在
资产/脚本/Board/Board.cs:111)
Board.GetSquare(UnityEngine.Vector2 currentPos)(位于
资产/脚本/Board/Board.cs:111)
Rook.GetMoves(System.Boolean过滤器)(在
Assets/Scripts/Piece/Pieces/Rook.cs:26)
King.IsChecked()(位于Assets/Scripts/Piece/Pieces/King.cs:152)
King.GetMoves(System.Boolean过滤器)(在
资产/脚本/片断/片断/国王.cs:77)
King.IsChecked()(位于Assets/Scripts/Piece/Pieces/King.cs:152)
...
Square
是我创建的一个类,boardNotation
是字典。在其他脚本的一些重大代码更改之后,这一问题似乎经常出现在同一行代码中,这也会导致在发生重大代码更改时它自行消失。是什么导致了这个问题
以下是所涉及的方法
public class Board : MonoBehaviour
{
public Square GetSquare(Vector2 currentPos)
{
foreach(Square square in boardNotation.Values)
{
Vector2 squarePos = new Vector2(square.transform.position.x, square.transform.position.y);
if(currentPos == squarePos)
{
return square;
}
}
return null;
}
}
public Class King : Piece
{
public override List<Square> GetMoves(bool filter)
{
List<Square> _moves = new List<Square>();
int range = 1;
bool isCheck = IsChecked();
foreach (Vector2Int dir in dirs)
{
for (int i = 1; i <= range; i++)
{
Vector2 pos = Vect3PosToVect2Pos(transform.position) + dir * i;
Square newSquare = board.GetSquare(pos);
if (newSquare)
{
if (newSquare.pieceOn != null)
{
if (newSquare.pieceOn.team == team)
break;
_moves.Add(newSquare);
break;
}
_moves.Add(newSquare);
}
}
}
if (filter)
_moves = FilterMoves(_moves);
return _moves;
}
public bool IsChecked()
{
Piece[] pieces = gm.GetPieces().ToArray();
for(int i = 0; i < pieces.Length; i++)
{
if (pieces[i].team == team)
continue;
List<Square> _moves = pieces[i].GetMoves(false);
if (_moves.Contains(board.GetSquare(transform.position)))
{
return true;
}
}
return false;
}
}
public class Rook: Piece
{
public override List<Square> GetMoves(bool filter)
{
List<Square> _moves = new List<Square>();
int range = board.GetBoardWH();
foreach(Vector2Int dir in dirs)
{
for(int i = 1; i <= range; i++)
{
Vector2 pos = Vect3PosToVect2Pos(transform.position) + (dir * i);
Square newSquare = board.GetSquare(pos);
if (newSquare)
{
if (newSquare.pieceOn != null)
{
if (newSquare.pieceOn.team == team)
break;
_moves.Add(newSquare);
break;
}
_moves.Add(newSquare);
}
}
}
if (filter)
_moves = FilterMoves(_moves);
return _moves;
}
}
公共类委员会:单一行为
{
公共广场GetSquare(矢量2当前位置)
{
foreach(boardNotation.值中的正方形)
{
Vector2 squarePos=新的Vector2(square.transform.position.x,square.transform.position.y);
如果(currentPos==squarePos)
{
返回广场;
}
}
返回null;
}
}
公共课王:一篇
{
公共覆盖列表GetMoves(布尔过滤器)
{
列表_moves=新列表();
int范围=1;
bool isCheck=IsChecked();
foreach(矢量2int dir在dirs中)
{
对于(inti=1;i不确定,可能您正试图在一个太平圈(?)
foreach(myDictionary中的KeyValuePair kvp)
{
WriteLine(“Key={0},Value={1}”,kvp.Key,kvp.Value);
}
实际上是这样的:(其中var是键的类型)
foreach(键盘符号中的KeyValuePair正方形)
{
Vector2 squarePos=新的Vector2(square.Value.transform.position.x,square.Value.transform.position.y);
如果(currentPos==squarePos)
{
返回广场;
}
}
我想,由于缺乏代码,我不确定。“堆栈溢出”通常意味着“无限递归”…我根本没有看到任何递归。请用1)更新您的帖子确切的错误消息,以及2)堆栈跟踪的相关部分。您应该能够从异常中复制/粘贴这两个部分。此代码可能导致StackOverflowException
的唯一方法是如果您已经几乎完全耗尽了调用堆栈中的可用空间。此处没有足够的信息来回答此请求ion,您能创建一个最小且可重复的示例吗?有关更多信息,请参阅。一个很难发现的典型示例,特别是在您发布的稀疏代码中,是由于属性实现不好造成的。请考虑:private string\u s=“init”;public string s{get{return s;}
。请注意,getter是根据属性而不是支持字段来实现的。当您访问S
时,getter会访问S
,并最终访问kaboom和堆栈溢出。您可以使用setter执行相同的操作。查看boardNotation.Values
和square.transform.position.x的每一位(和.y
)查看您的代码。GetMoves
在早期调用IsChecked
。然后,在IsChecked
中,调用pieces[i]。GetMoves(false)
。想想看。如果A调用B,B调用A,除非你非常非常小心如何结束递归,否则你将永远这样做。每个调用都会分配一些堆栈。最终你会用完。修复它需要你重新思考如何做。为什么在属性内循环会成为一个问题?如果你能解释代码是如何进入的您的答案可能会产生堆栈溢出,这是一个合理的建议…到目前为止,答案中显示的代码没有合理的方法产生该异常…@Llama假设该属性是一个IEnumerator,并且实现良好,没有。(对不起,我是新手,我发布了类似答案的内容,而不是问题xD)MS说每个字典的最佳标准是什么,这是因为你可以将列表作为值进行迭代,因此可能会造成混淆,也不建议使用var。我不确定字典是否是一个好的用法,它是为一个键而优化的,而不是循环值,即TryGetValue()。(如果我错了,请纠正我)@AlexeiLevenkov,抱歉,这不是anwser!我不能我不是专家,MS说:“字典可以同时支持多个阅读器,只要集合不被修改。即使如此,通过集合枚举本质上也不是线程安全的过程。”我不确定会引发什么样的异常…建议是锁定还是监视…在OP的代码中实际上根本没有字典
。。还有:为什么使用var
不好?为什么迭代字典本身或例如值不好?
foreach(KeyValuePair<string, string> kvp in myDictionary )
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
foreach(KeyValuePair<var,Square> square in boardNotation)
{
Vector2 squarePos = new Vector2(square.Value.transform.position.x, square.Value.transform.position.y);
if(currentPos == squarePos)
{
return square;
}
}