当代码从 keydown 事件移动到函数中时,C# 变量会重置 - 谁能解释为什么?



我在VS Express 2010中使用C#窗口表单应用程序。为了学习,我正在玩一些代码。我有一个表单对象,我想通过按键不断向一个方向移动 - 它的原始代码工作正常。

在尝试通过将"移动"代码移动到函数中来整理它的过程中,代码不再像以前一样工作。现在,我的对象不再从当前位置沿所选方向移动,而是在每次按下某个键时重置其位置。我想知道为什么会发生这种情况,因为我所做的更改绝对是最小的。请参阅代码:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{          
if (e.KeyCode == Keys.Down)
{
direction = 4;
}
if (e.KeyCode == Keys.Up)
{
direction = 2;
}
if (e.KeyCode == Keys.Right)
{
direction = 3;
}
if (e.KeyCode == Keys.Left)
{
direction = 1;
}
while (direction != 0)
{
Application.DoEvents();
if (direction == 1)
{
X = X - 1;
}
else if (direction == 2)//up
{
Y = Y - 1;
}
else if (direction == 3)
{
X = X + 1;
}
else if (direction == 4)//down
{
Y = Y + 1;
}
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}

当我将 while 循环移动到移动函数中时,变量 X 和 Y 在每次按键时都会重置为 0。 此代码如下所示:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{          
if (e.KeyCode == Keys.Down)
{
direction = 4;
}
if (e.KeyCode == Keys.Up)
{
direction = 2;
}
if (e.KeyCode == Keys.Right)
{
direction = 3;
}
if (e.KeyCode == Keys.Left)
{
direction = 1;
}
movement(X, Y, direction);
}

我觉得我在这里错过了一些明显的东西,但我不明白为什么它的行为不同。感谢您的任何帮助:)

编辑 1:移动函数的代码:

movement(int X, int Y, int direction)
{
while (direction != 0)
{
Application.DoEvents();
if (direction == 1)
{
X = X - 1;
}
else if (direction == 2)//up
{
Y = Y - 1;
}
else if (direction == 3)
{
X = X + 1;
}
else if (direction == 4)//down
{
Y = Y + 1;
}
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}            
}

我想您的movement方法更改了作为参数提供的XY。但是,参数XY是"按值"传递的,而不是"按引用"传递的。

如果你想做到这一点,你要么必须使用类变量,并删除方法调用中的参数,要么使用ref,我将演示:

movement(ref X, ref Y, direction);

和:

private void movement(ref int X, ref int Y, int direction)
{ }
private void Form1_KeyDown(object sender, KeyEventArgs e)
{          
if      (e.KeyCode == Keys.Down)  direction = 4;
else if (e.KeyCode == Keys.Up)    direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left)  direction = 1;
while (direction != 0)
{
Application.DoEvents();
if      (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}

可以重写:

private void SetDirection(KeyEventArgs e)
{
if      (e.KeyCode == Keys.Down)  direction = 4;
else if (e.KeyCode == Keys.Up)    direction = 2;
else if (e.KeyCode == Keys.Right) direction = 3;
else if (e.KeyCode == Keys.Left)  direction = 1;
}
private void ApplyMovement()
{
while (direction != 0)
{
Application.DoEvents();
if      (direction == 1) X--;
else if (direction == 2) Y--;
else if (direction == 3) X++;
else if (direction == 4) Y++;
Thread.Sleep(100);
label1.Location = new Point(X, Y);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{          
SetDirection(e);
ApplyMovement();
}

你必须明白变量XYdirection是类成员,因此可以从类中的任何位置访问它们,当你调用movement(X, Y, direction)时,movement使用这些变量的副本,所以当你在movement方法中执行X = X + 1时,你实际上并没有改变类的X值, 但仅限于它的副本。这意味着变量 X 和 Y(即.class成员)不会在每次按键时重置为 0。事实上,他们永远不会被设置为其他任何东西

请注意,您也可以使用switch语句而不是所有这些语句if

switch (direction)
{
case 1: X--; break; // left
case 2: Y--; break; // up
case 3: X++; break; // right
case 4: Y++; break; // down
}

相关内容

最新更新