【问题标题】:Assign to null reference type分配给空引用类型
【发布时间】:2016-12-29 06:33:07
【问题描述】:

请理解我看到并关注了该问题,但不确定如何彻底解决该问题。我正在尝试运行我的 Add 方法,迭代直到找到我的密钥或当前节点为空,然后将 reference 返回到节点并分配它是否为空.我的代码(见 add 方法中的注释):

public class MyClass<TKey, TValue>
{
    private Node _baseNode;

    public void Add(TKey key, TValue value)
    {
        var newNode = new Node(key, value);

        //this returns null, as is expected.
        var nodeToUpdate = TraverseDown(ref _baseNode, newNode.Key);

        if (nodeToUpdate != null)
            throw new ArgumentException("Cannot add a duplicate key.");

        //here, I try to assign a value to _baseNode because I'd like
        //nodeToUpdate to hold the reference to _baseNode
        nodeToUpdate = newNode;
    }

    private Node TraverseDown(ref Node currentNode, int keyToFind)
    {
        if (currentNode == null || currentNode?.Key == keyToFind 
            || currentNode?.Edge == null)
        {
            //on first add, this is what is getting hit - as expected
            return currentNode;
        }
        else
        {
            //these are being explicitly set to local variables because i was 
            //experimenting with passing them byRef, and that can't be done on 
            //properties
            var leftNode = currentNode.Edge.LeftNode;
            var rightNode = currentNode.Edge.RightNode;
            return keyToFind < currentNode.Key 
                            ? TraverseDown(ref leftNode, keyToFind) 
                            : TraverseDown(ref rightNode, keyToFind);
        }
    }
}

让 TraverseDown 方法接受节点 byRef 的全部意义在于尝试返回对已找到的任何节点的引用,即使它为空。在这种情况下,这是添加的第一项,因此 TraverseDown 方法应该返回对我的 _baseNode 的引用,默认为 null。然而,这只是将局部变量设置为 newNode,而 _baseNode 保持为空。

我确信对此有一个简单的答案,但我已经研究了一点,但一无所获。请,非常感谢任何帮助!

【问题讨论】:

    标签: c# .net c#-4.0 null pass-by-reference


    【解决方案1】:

    在您的 TraverseDown 方法中没有您实际分配 ref currentNode 的行。相反,您返回它的值。当您传递ref 参数时,并不意味着该值将在整个方法范围内被视为引用。 参数本身将被视为参考,而不是其值。所以当你写...

    return currentNode;
    

    您返回currentNode,而不是引用。由于值为null,因此您始终返回null(因为您的if (currentNode == null... 语句)。

    当你分配...

    nodeToUpdate = newNode;
    

    ...您只需分配一个null 引用。

    当你真正想在TraverseDown中给_baseNode赋值时,需要在方法中设置currentNode

    currentNode = //Value
    

    请注意 in C# 7.0 there will be ref returns,它的行为方式与您在方法中对待 currentNode 的方式相同。

    【讨论】:

    • 感谢您如此迅速地回复,这非常有意义。只需阅读 C# 7.0 链接,那里有一些有趣的东西。我想这是按预期运行的,但是使代码的编写方式变得复杂。我需要 TraverseDown 方法来执行搜索,而不是分配。认为这意味着我只需要在 add 方法中明确设置顶部节点,然后可能会返回父节点,而不是我想要直接操作的节点。除非你有其他想法?再次感谢!
    • @Switch386,如果您不让方法进行分配,则作为引用传递没有多大意义。如果您不想这样做,返回您想要添加新子节点的节点(即新的父节点)确实更有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 2019-06-02
    • 2021-08-15
    相关资源
    最近更新 更多