在下面的代码中,我试图在测试方法中将node设置为null。当我这样做时,节点在方法的范围内变为空,但是父母'不会变为空。我的理解是将对象作为引用传递给方法,并且可以在方法内直接操作。我认为我的概念理解存在问题。你能解释为什么将节点分配给null并不将父节点赋给null。
class Program
{
static void Main(string[] args)
{
Node parent = new Node();
parent.key = 50;
parent.left = new Node();
Test.test(parent);
}
}
class Test
{
public static void test(Node node)
{
node.key = 1111;
node = null;
}
}
class Node
{
public object key { get; set; }
public Node left = null;
public Node right = null;
}
答案 0 :(得分:5)
您实际上并未通过此处的引用将parent
传递给node
。这意味着正在将parent
的值复制到node
函数中的test
。在这种情况下,该值只指向Node
对象。
node.key = 1111
按预期工作,因为它使用该值来访问parent
也指向的同一对象。即,node
和parent
都包含指向内存中相同位置的值。因此,两者都可以观察到修改。
但是当您说node = null
时,您要为node
函数中的test
变量分配一个新值。这意味着您将存储为该特定变量中的值的指针更改为null
,这绝不会修改parent
的值 - 它仍然指向Node
对象。 / p>
注意我的业余ASCII艺术,但我认为它有点像这样:
Test.test(parent);
<node object>
^ ^
. .
. .
. .
+------.----+ . +-----------+
| . | . |
| . | (-> copied to) | . |
| parent | | node |
+-----------+ +-----------+
Program.Main scope Test.test scope
node = null;
<node object>
^
.
.
.
+------.----+ +-----------+
| . | | |
| . | | |
| parent | | node=null |
+-----------+ +-----------+
Program.Main scope Test.test scope
然而,如果您碰巧使用public static void test(ref Node node)
,您可能会更像这样想:
Test.test(parent);
<node object>
^
.
.
.
+------.----+ +-----------+
| parent <============================ node |
| | | |
| | | |
+-----------+ +-----------+
Program.Main scope Test.test scope
node = null;
<node object>
Lonely
+-----------+ +-----------+
| parent <============================ node |
| = | | |
| null | | |
+-----------+ +-----------+
Program.Main scope Test.test scope
答案 1 :(得分:4)
这是因为参数是按值传递的,因此在测试方法中,已创建父变量的副本,您只需将变量副本设置为null。虽然您仍然可以操作对象,因为复制变量指向堆中的对象。
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
SetNull(foo);
Console.WriteLine(foo.ID);// print 2
}
private static void SetNull(Foo foo)
{
foo.ID = 2;
foo = null;
}
}
class Foo
{
public int ID { get; set; }
}
答案 2 :(得分:2)
使用ref
关键字:
public static void Test(ref Node node) {
node = null;
}
// Usage
Node parent = ...
Test( ref parent );
Assert( parent == null );
答案 3 :(得分:0)
此处使用不同的变量名重写此方法,例如:
public static void test(Node PassedNode)
{
PassedNode.key = 1111;
PassedNode = null;
}
PassedNode
方法中的 test
指向最初传入的Node parent = new Node();
对象,因此当您修改PassedNode
内test
的属性值时1}}方法,然后这些更改将影响Main方法中的对象,因为只有一个对象。当您编写PassedNode = null
时,PassedNode
方法中的test
不再指向原始对象,而是发生的一切:对象本身仍然存在。如果要清除原始引用,则需要在调用方法中执行此操作。