Foreach 循环遍历字典导致 StackOverflowException

问题描述

我的错误

StackOverflowException Board.GetSquare(UnityEngine.Vector2 currentPos)(在 Assets/Scripts/Board/Board.cs:111)

堆栈跟踪是

Board.GetSquare(UnityEngine.Vector2 currentPos) ( at 
Assets/Scripts/Board/board.cs:111)
Board.GetSquare (UnityEngine.Vector2 currentPos) (at 
Assets/Scripts/Board/Board.cs:111)
Rook.GetMoves (System.Boolean filter) (at 
Assets/Scripts/Piece/Pieces/Rook.cs:26)
King.IsChecked () (at Assets/Scripts/Piece/Pieces/King.cs:152)
King.GetMoves (System.Boolean filter) (at 
Assets/Scripts/Piece/Pieces/King.cs:77)
King.IsChecked () (at 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;
}
}

解决方法

不确定,也许您正试图在礼节 (?) 中循环

Check Dictionary iteration on MS docs

foreach(KeyValuePair<string,string> kvp in myDictionary )
{
 Console.WriteLine("Key = {0},Value = {1}",kvp.Key,kvp.Value);
}

实际上是这样的:(其中 var 是键的类型)

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

我认为,由于缺少代码,不确定。