C# 导致StackOverflowException的字典上的Foreach循环

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)(位于 资产/

我的错误是

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