gpt4 book ai didi

c# - Visual Studio 传递变量作为引用?

转载 作者:太空宇宙 更新时间:2023-11-03 21:35:49 25 4
gpt4 key购买 nike

我已经在这个程序上工作了一两个小时了,每次我尝试调试它时,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;
}

最佳答案

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

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

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

myObject = new Person();

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

这是最容易思考的事情之一(我不是 100% 确定这是否属实,但它让思考这个问题变得更容易)。是指向堆中对象并存储在堆栈中的指针。当您设置 byvalbyref/ref 时,它作用于 stack 中的对象,而不是 stack 中的对象。即 Byval/ByRef 永远适用于堆。

编辑 Here是 Jon Skeet 支持这一点的支持性回答。他还链接到 this文章

更新

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

This answer从稍微不同的角度(结构是类的一部分)处理它,但我认为它明白了这一点

关于c# - Visual Studio 传递变量作为引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21953560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com