Visual Studio传递变量作为参考?

时间:2014-02-22 11:21:12

标签: c# visual-studio-2013

我一直在研究这个程序一两个小时,每次我尝试调试它时,visual studio决定更改currentGuess.guessLine中的值,我不明白为什么。他们没有通过引用传递任何地方,他们应该更改的唯一时间是在评论'获取用户猜测'。有人可以帮忙,因为它让我疯了吗?我提供了以下代码:(我删除了任何完全不相关的方法,以缩短它。

我正在使用visual studio professional,我现在已经重写了3次这段代码,但我仍然无法弄清楚它为什么会发生。任何帮助将不胜感激。

struct History
    {
        public Guess[] previousGuesses;
        public int noOfPreviousGuesses;
    }
    struct Guess
    {
        public int[] guessLine;
        public Hint givenHint;
    }
    struct Hint
    {
        public int blackPegs;
        public int whitePegs;
    }

    static void Main(string[] args)
    {
        Mastermind(3, 3);
    }

    static void Mastermind(int N, int M)
    {
        bool gameFinished;
        int playAgain;
        History gameHistory;
        Guess currentGuess;
        int[] secretCode;

        do
        {
            //Game start
            gameFinished = false;

            //Reset history
            gameHistory.previousGuesses = new Guess[0];
            gameHistory.noOfPreviousGuesses = 0;

            //Generate secretCode
            secretCode = GenerateSecretCode(N, M);

            do
            {
                //Get guess from user
                currentGuess.guessLine = GetGuessLine(N, M);

                //Evaluate guess
                gameFinished = EvaluateGuess(currentGuess.guessLine, secretCode, N);

                if (gameFinished == false)
                {
                    //Generate hint
                    currentGuess.givenHint = GenerateHint(currentGuess.guessLine, secretCode, N);

                    //Add guess to history
                    gameHistory = AddGuessToHistoryQueue(currentGuess, gameHistory);

                    //Output history
                    OutputHistory(gameHistory, N);
                }

            } while (gameFinished == false);

            //Ask to play again
            playAgain = GetValueFromUser("Enter 0 or a positive value to play again, otherwise enter a negative value: ");

        } while (playAgain >= 0);
    }

    /// <summary>
    /// Gets a guess line from the user.
    /// Validates each value using above procedure.
    /// </summary>
    /// <param name="codeLength">The length of the code being used.</param>
    /// <param name="noOfColours">The number of colours allowed.</param>
    /// <returns>The line entered.</returns>
    static int[] GetGuessLine(int codeLength, int noOfColours)
    {
        int[] guessLine;

        guessLine = new int[codeLength];

        for (int count = 0; count < codeLength; count++)
        {
            //Get guessLine[count] from user
            guessLine[count] = GetValueFromUserInRange(1, noOfColours, "Please enter guess at position " + count + ": ");
        }

        return guessLine;
    }

    /// <summary>
    /// Compares the given guess to the given code.
    /// Returns true if guess and code match exactly otherwise
    /// returns false.
    /// </summary>
    /// <param name="guess">The guess being compared.</param>
    /// <param name="code">The code to be compared against.</param>
    /// <param name="codeLength">The length of the code and guess.</param>
    /// <returns></returns>
    static bool EvaluateGuess(int[] guess, int[] code, int codeLength)
    {
        bool correctGuess;

        correctGuess = true;

        for (int count = 0; count < codeLength; count++)
        {
            if (guess[count] != code[count])
            {
                //Found inconsistency
                correctGuess = false;
                break;
            }
        }

        return correctGuess;
    }

    /// <summary>
    /// Generates a hint through finding all matching values,
    /// changing their values and incrementing the black pegs total.
    /// Then calculates white pegs by checking for matching values again.
    /// </summary>
    /// <param name="guess">The guess requiring a hint.</param>
    /// <param name="code">The code for the guess to be compared to.</param>
    /// <param name="codeLength">The length of the code/guess.</param>
    /// <returns>The hint generated.</returns>
    static Hint GenerateHint(int[] guess, int[] code, int codeLength)
    {
        Hint newHint;

        newHint.blackPegs = 0;
        newHint.whitePegs = 0;

        //Calculate blackPegs
        for (int count = 0; count < codeLength; count++)
        {
            if (guess[count] == code[count])
            {
                newHint.blackPegs = newHint.blackPegs + 1;

                //Hide values
                guess[count] = 0;
                code[count] = 0;
            }
        }

        //Calculate white pegs
        for (int guessCount = 0; guessCount < codeLength; guessCount++)
        {
            //Ensure current guess value hasn't been used
            if (guess[guessCount] != 0)
            {

                //Check for matching value in code
                for (int codeCount = 0; codeCount < codeLength; codeCount++)
                {
                    if (guess[guessCount] == code[codeCount])
                    {
                        //Found match
                        newHint.whitePegs = newHint.whitePegs + 1;

                        //Hide values
                        guess[guessCount] = 0;
                        code[codeCount] = 0;
                    }
                }

            }
        }

        return newHint;
    }

1 个答案:

答案 0 :(得分:4)

这是许多开发人员常犯的错误。参数可以作为ByValByRef传递(使用VB表示法)。但这样做并不是大多数人所认为的那样。

对于值类型(例如int等 - 驻留在堆栈中的任何内容)。该值本身被复制到一个新的内存空间,并传递给该方法。因此,对值的更改不会影响原始值。

对于引用类型(例如,对象,类等 - 驻留在堆中的任何内容)。 指针被复制并传递给方法。但是,指针仍然指向内存中的同一对象。因此,对象内部属性的更改仍将反映在调用方法中。 不会唯一反映的是,如果你这样做:

myObject = new Person();

此时,传入方法的指针将被重置为指向一个全新的对象。但是来自调用方法的原始指针仍然指向原始对象。因此,它不会看到这些变化。

最容易思考的问题之一(我不是百分之百确定这是否属实,但它更容易考虑这一点)。是指针到堆中的对象并存储在堆栈中。当您设置byvalbyref / ref时,它会对堆栈中的对象进行操作,而不是堆中的对象 。即Byval / ByRef 只有适用于堆。

修改 Here是Jon Skeet支持的回答。他还链接到this文章

<强>更新

根据您的评论提供的其他信息。你的结构包含引用类型(int[]是一个int数组 - 数组是引用类型),因此它们会自动移动到堆中(据我所知,至少)。

This answer从一个稍微不同的角度解决它(结构是一个类的一部分),但我认为它得到了重点