值类型和引用类型问题

本文关键字:问题 引用类型 类型 | 更新日期: 2023-09-27 17:56:57

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

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

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

值类型和引用类型问题

这样

看。

让我们将 swap 方法中的参数重命名为"x"和"y",因为使它们与局部变量相同只会令人困惑。

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

你有两张纸,上面写着"苹果"和"橙色"。这些是对对象的引用。

您有两个框,一个标记为"第一",另一个标记为"第二"。

你把"APPLE"放在第一位,"ORANGE"放在第二位。

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

你制作一份苹果的复印件,把它放在x中。你复印一份橙色的复印件,把它放在y中。

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

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

您有两个框,一个标记为"第一",另一个标记为"第二"。

你把"APPLE"放在第一位,"ORANGE"放在第二位。

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

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

有意义?

这里有各种不同的东西:

  • 对象在堆中存在。暂时忘记他们
  • 对对象的引用是存储在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(等)或"对对象的引用"。无论哪种方式,逻辑都是相同的。

Swap 方法中的参数指向的对象是对First的引用,Main 中的Second对象,但参数本身是 Swap 方法的本地。

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

您不是将其作为引用传递,您需要明确声明您正在传递引用:

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

按值传递对对象的引用(按值传递是 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 .

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

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

例如

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

您需要通过引用传递。

下面是有关按重新围栏传递、按值传递的一些额外信息: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;
}