无法在方法

时间:2015-06-02 00:27:23

标签: c#

在下面的代码中,我试图在测试方法中将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;
    }

4 个答案:

答案 0 :(得分:5)

您实际上并未通过此处的引用将parent传递给node。这意味着正在将parent的值复制到node函数中的test。在这种情况下,该值只指向Node对象。

node.key = 1111按预期工作,因为它使用该值来访问parent也指向的同一对象。即,nodeparent都包含指向内存中相同位置的值。因此,两者都可以观察到修改。

但是当您说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();对象,因此当您修改PassedNodetest的属性值时1}}方法,然后这些更改将影响Main方法中的对象,因为只有一个对象。当您编写PassedNode = null时,PassedNode方法中的test不再指向原始对象,而是发生的一切:对象本身仍然存在。如果要清除原始引用,则需要在调用方法中执行此操作。