值类型和引用类型问题

时间:2011-05-20 10:56:44

标签: c# .net swap reference-type

您好 我正在尝试简单地交换两个对象。我的代码是

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

由于对象是引用类型,因此应将其引用传递给方法,并且应该交换。 为什么不发生?

7 个答案:

答案 0 :(得分: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”放在第二位。

您向框First添加新标签;它现在也可以称为x。第二个也可以称为y。

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

有意义吗?

答案 1 :(得分:5)

这里有各种不同的东西:

  • 对象在堆中存活。暂时忘掉它们
  • 对象的引用是存储在First和第二
  • 中的内容
  • Main
  • 中有两个变量
  • Swap
  • 中有两个参数

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

在该行:

Swap(First, Second);

将两个变量的传递给Swap。在这种情况下,First / Second对盒装对象的引用

下一步;

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

唯一的区别是x是1等,而ref x是对变量x的引用。在通过引用传递时,引用类型与值类型完全无关;唯一重要的是要理解你默认传递变量的,其中变量的1(等)或“a引用一个对象“。无论哪种方式,逻辑都是一样的。

答案 2 :(得分:1)

Swap方法中的参数所指向的对象是对FirstSecondMain个对象的引用,但参数本身是Swap的本地对象{1}}方法。

因此,如果您在Swap内写了First = 1; Second = 2 ;,那么您会看到Main内对象的变化。但是,您只需将参数变为Swap 指向(通过将它们指定给另一个对象),并且根本不更改对象。如果您尝试在null方法中将对象设置为Swap,情况也是如此。

答案 3 :(得分:1)

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

 Swap(ref First,ref Second);

 private static void Swap(ref object First,ref object Second)

答案 4 :(得分:1)

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

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

E.g。

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

答案 5 :(得分: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或更高版本,你最好定义一个可以接受任何类型参数的generic版本的函数,而不是object类型。例如:

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

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

答案 6 :(得分: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;
}