值类型和引用类型问题
本文关键字:问题 引用类型 类型 | 更新日期: 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;
}