3

嗨,我正在尝试对两个对象进行简单交换。我的代码是

void Main()
{
  object First = 5;
  object Second = 10;

  Swap(First, Second);
  //If I display results it displays as 
  //Value of First as 5 and Second as 10
}

private static void Swap(object First, object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

由于对象是引用类型,它的引用应该传递给方法并且应该交换。为什么没有发生?

4

7 回答 7

6

这样看。

让我们将交换方法中的参数重命名为“x”和“y”,因为让它们与本地参数相同只会令人困惑。

你有一个苹果和一个橙子。两个对象。

你有两张纸,上面写着“APPLE”和“ORANGE”。这些是对对象的引用。

您有两个框,一个标为 First,一个标为 Second。

你把“APPLE”放在第一个,“ORANGE”放在第二个。

现在您又获得了两个标记为 x 和 y 的框。

你制作一份 APPLE 的复印件并将其放入 x 中。你把 ORANGE 复印一份放在 y 里。

现在交换 x 和 y 的内容。APPLE 和 ORANGE 仍然是引用,但您没有更改 First 和 Second 的内容。您更改了 x 和 y 的内容。

现在假设您将“ref”添加到参数 x 和 y 的声明中。现在这意味着:

您有两个框,一个标为 First,一个标为 Second。

你把“APPLE”放在第一个,“ORANGE”放在第二个。

您首先向框添加一个新标签;它现在也可以称为 x。Second 也可以称为 y。

你交换 x 和 y 的内容。由于它们只是 First 和 Second 的别名,因此 First 和 Second 的内容被交换。

说得通?

于 2011-05-20T14:24:40.883 回答
5

这里有各种不同的东西:

  • 对象生活在堆中。暂时忘记他们
  • 对对象的引用是存储在其中的First,其次是
  • 你有两个变量Main
  • 你有两个参数Swap

现在; 重要的是“引用类型/引用”和“按引用传递”之间的区别。它们是完全无关的。

在行中:

Swap(First, Second);

您将两个变量的值传递给Swap. 在这种情况下,/的对装箱对象的引用。FirstSecond

下一个;

private static void Swap(object First, object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

在这里,您交换两个本地参数的值,但它们完全独立于其他任何参数。如果我们希望调用者看到的变化(即重新分配),我们需要通过引用传递:

private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

现在的值First不再是对装箱对象的引用;它是对装箱对象的引用。在调用方,我们使用:

Swap(ref First,ref Second);

这意味着传递变量的引用First,而不是传递变量的值First

请注意,我说您可以忘记存在对象的事实?如果我们使用,上面的一切都是一样的:

int x = 1, y = 2;
Swap(ref x, ref y);
void Swap(ref int a, ref int b) {
    var tmp = a; a = b; b = tmp;
}

唯一的区别是 的值为1x等,并且ref x是对变量 x 的引用。在按引用传递中,引用类型与值类型完全无关;唯一重要的是理解默认情况下传递变量的,其中变量的1(等),或“对对象的引用”。无论哪种方式,逻辑都是一样的。

于 2011-05-20T11:10:48.230 回答
1

方法内部的参数指向的对象是对内部的和对象Swap的引用,但参数本身是方法本地的。FirstSecondMainSwap

所以如果你在里面Swap写了First = 1; Second = 2;,你就会看到里面的对象的变化Main。但是,您只更改参数Swap 指向的内容(通过将它们分配给另一个对象),而根本不更改对象。如果您尝试将对象设置null在方法内部,情况也是如此Swap

于 2011-05-20T11:01:54.360 回答
1

您没有将其作为参考传递,您需要明确声明您正在传递参考:

 Swap(ref First,ref Second);

 private static void Swap(ref object First,ref object Second)
于 2011-05-20T11:02:06.523 回答
1

而不是通过值传递对对象的引用,您需要通过引用传递它们。换句话说,您需要将引用传递给对象的引用

这是使用ref关键字实现的。

例如

private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}
于 2011-05-20T11:02:24.570 回答
1

您正在按值传递对对象的引用(按值传递是 C# 中的默认值)。

相反,您需要通过引用(使用ref关键字)将对象传递给函数。

private static void Swap(ref object first, ref object second)
{
    object temp = first;
    first = second;
    second = temp;
}

void Main()
{
    object first = 5;
    object second = 10;

    Swap(ref first, ref second);
}

当然,如果您使用的是 C# 2.0 或更高版本,则最好定义此函数的泛型版本,该版本可以接受任何类型的参数,而不是object类型。例如:

private static void Swap<T>(ref T first, ref T second)
{
    T temp;
    temp = first;
    first = second;
    second = temp;
}

然后,您还可以使用正确的类型声明变量, int.

于 2011-05-20T11:02:58.653 回答
0

您需要通过引用传递。

这里有一些关于 pass-by-refence、pass-by-value 的额外信息: http ://www.yoda.arachsys.com/csharp/parameters.html ,试试这个:

void Main()
{
 object First = 5;
 object Second = 10;

  Swap(ref First, ref Second);
  //If I display results it displays as 
  //Value of First as 5 and Second as 10
}


private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}
于 2011-05-20T10:59:55.603 回答