为什么我不能在函数中实例化一个对象

时间:2016-02-10 10:50:44

标签: c#

所以基本上我有一个NodeTree类:

public class NodeTree
{
    public NodeTree(int value, NodeTree left, NodeTree right)
    {
        Value = value;
        Right = right;
        Left = left;
    }

    public int Value { get; set; }
    public NodeTree Right { get; set; }
    public NodeTree Left { get; set; }
}

在我的主要内容中,我想做一些像

这样的事情
NodeTree root = null;
Algo.InsertValueIt(root, 8);

其中InsertValueIt()是我的静态类Algo中的一个方法:

 public static void InsertValueIt(NodeTree root, int val)
    {
        var newNode = new NodeTree(val, null, null);
        if (root == null)
        {
            root = newNode;
        }
    }

在我的方法中,一切都按预期工作,但回到我的主要,我的对象根仍然是空的。 我感到困惑的原因是我给我的方法一个引用,所以它应该将地址的值修改为我分配的新空间。

我认为我可以通过返回NodeTree来解决我的问题,但有没有办法用void返回类型来做?

3 个答案:

答案 0 :(得分:5)

您需要定义要通过引用传递的参数,以便修改原始值(请注意ref关键字):

public static void InsertValueIt(ref NodeTree root, int val) {
    ...

同样在调用方法时,您需要使用ref标记参数:

Algo.InsertValueIt(ref root, 8);

...否则您只修改该功能中的本地副本。

答案 1 :(得分:2)

将引用类型传递给方法时会发生什么?
声明为引用类型的变量保存已分配类型实例的内存地址(调用代码中的 root )。此地址的值将复制到在堆栈上为被调用方法创建的新变量(InsertValueIt中的)。通过新变量使用该地址,您将能够更改实例的每个公共属性或调用任何方法(假设传递的地址不为null)。

如果您在此本地变量上调用new,会发生什么?
在堆的类型上分配新的内存块,调用构造函数来初始化所有内容,并且此块的内存地址存储在InsertValueIt内的LOCAL变量中。

您原来的(调用代码中的根)不受此更改的影响。 (仍然保持为空)。使用ref关键字可以解决这个问题'消失,但我建议使用一个创建Node的方法,然后将其返回给调用方法。

如果你想更深入地理解这个主题,我推荐这两篇文章:

来自 Joseph Albahari

C#Concepts: Value Types vs Reference Types 来自 Jon Skeet

Parameter Passing in C#

答案 2 :(得分:0)

在InsertValueIt中分配的根值未在任何执行路径中使用,因此您应在参数声明中添加ref关键字