请参阅下面提到的以下代码行:
byte[] a = { 1, 2, 3, 4 };
byte[] b = a; // b will have all values of a.
a = null;
在C#byte[]
中是引用类型。现在,如果第3行中有a = null
,那么为什么b
不是null,因为它是引用类型。如果我们检查b
,它仍然会包含a
的所有值。
答案 0 :(得分:7)
首先在内存中的某个位置创建一个数组,例如从地址1000
开始。 a
是一个引用,它不包含数组,它包含地址1000
。 b
也包含此地址。在第3行中,您更改a
以指向null
,但b
仍然指向地址1000
中的数组。
您编辑了引用(a
),但未编辑它引用的对象({1,2,3,4}
)。
答案 1 :(得分:7)
这实际上是reference types的工作方式。
正如您所说,byte[]
与所有其他数组一样是的引用类型。让我们逐行分析你的样本;
byte[] a = { 1, 2, 3, 4 };
- >您在内存中创建了一个字节数组,a
是一个数组引用。
byte[] b = a;
- >您的b
引用的同一个对象a
{ 1, 2, 3, 4 }
但它们是不同的引用。
a = null;
- >您的a
未在内存中的任何位置引用,但这不会影响b
。
答案 2 :(得分:3)
您的问题假设您在完成作业时:
byte[] b = a;
你正在制作某种类型的图表关联:
b -> a -> { 1, 2, 3, 4 }
当您将a
分配给null
时,会影响b
的值,因为:
b -> a -> null
但这不是复制引用的工作方式。复制引用时,实际上是a
引用的副本,如下所示:
a ----> { 1, 2, 3, 4 }
^
b ------------|
这就是为什么当您将a
分配给null
时,您不会影响b
的值,仅a
:
a ----> null { 1, 2, 3, 4 }
^
b ------------------------|
答案 3 :(得分:0)
您正在使b
指向包含byte
数组的内存地址。然后 ,您将a
指向null
。 b
保持不变。
答案 4 :(得分:0)
引用类型变量指向一个值。将一个ref类型变量分配给另一个时,将对其值的引用复制到变量本身。这就是b
仍然指向值表的原因。
答案 5 :(得分:0)
当类型是值类型时,表示此类型的变量存储实际数据。当类型是引用类型时,意味着此类型的变量存储对实际数据的引用。
在这两种情况下,从一个变量分配到另一个变量复制变量的内容。对于值类型,这意味着将值从一个变量复制到另一个变量,复制实际数据,从而创建新对象。对于引用类型,这意味着将引用从一个变量复制到另一个变量,复制引用但保留实际数据。要强调:对象未被复制,但引用是。引用的两个副本是独立的,即使很容易观察到它们在解除引用时指向同一个对象。
从这些中你可以很容易地看到从一个变量到另一个变量的赋值复制了对字节数组的引用,因此你有两个对字节数组的引用。之后,当您为其中一个变量赋值null时,您正在复制对它的空引用,将原始引用(存储在该变量中)覆盖到字节数组。所以,现在你没有对字节数组的两个引用,但只有一个引用 - 对象是相同的,但对它的引用是独立的。
(类似地,如果将字节数组重新分配给空变量,它并不意味着程序中指向null的所有变量将指向字节数组 - 仅你指定的那个。)