Почему иногда 2 объекта ссылаются на одно и то же, но не всегда - PullRequest
0 голосов
/ 18 февраля 2019

После последнего ответа: Рекурсивный метод для преобразования плоской коллекции в иерархическую коллекцию?

Я хочу использовать тот же метод CreateTree, но с другим объектом, чем Hierarchy: ItemNode:

public class ItemNode
{
    public string Id { get; set; }
    public Item Item { get; set; }
    public ICollection<ItemNode> Children { get; set; }
}

и определение Item:

public class Item
{
    public string ID { get; set; }
    public string Name { get; set; }
    public int Level { get; set; }
    public string ParentId { get; set; }
}

А вот методы CreateTree с ItemNode:

    static List<ItemNode> CreateTreeItems(IEnumerable<ItemNode> nodes)
    {
        Dictionary<string,ItemNode> idToNode = nodes.ToDictionary(n => n.Id, n => n);
        List<ItemNode> roots = new List<ItemNode>();
        ItemNode root = null;

        foreach (var n in nodes)
        {
            if (n.Item.ParentId == null)
            {
                if (root != null)
                {
                    roots.Add(root);
                }
                root = n;
                continue;
            }

            ItemNode parent = idToNode[n.Item.ParentId];
            //if (!idToNode.TryGetValue(n.Item.ParentId, out parent))
            //{
            //  //Parent doesn't exist, orphaned entry
            //}

            parent?.Children.Add(n);

            // RETURNS FALSE WHEREAS IN THE ORIGINAL METHOD IT RETURNS TRUE
            var test = Object.ReferenceEquals(parent, root);
            Debug.WriteLine(test);
        }


        if (root == null)
        {
            //There was no root element
        }

        roots.Add(root);
        return roots;
    }

Это не работает, потому что parent и root не ссылаютсятот же объект (тогда как в оригинальном методе это так).Я предполагаю, что это было связано с тем, что я добавил свойство Item в класс ItemNode.Но я не знаю, как это исправить.

Спасибо!

1 Ответ

0 голосов
/ 18 февраля 2019

Почему вы ожидаете, что ссылки на корневой и родительский узлы будут равны?Каждый корневой узел может быть родительским узлом, но не каждый родительский узел является корневым узлом.

Могут быть ситуации, когда ссылки равны, но это очень зависит от порядка сортировки коллекции nodes.На самом деле, когда корневой узел размещен раньше, чем дочерний узел 1-го уровня, вы увидите ситуацию, когда ссылки равны.

Я полагаю, ваша проблема в другом месте, например, она может не работать, если коллекция Nodes неУ вас вообще нет корневого узла.

Вот пример, попробуйте здесь https://dotnetfiddle.net/4r52xP

using System;
using System.Collections.Generic;
using System.Linq;

public class Hierarchy
{
    public Hierarchy(string iD, string name, int level, string parentID, string topParent)
    {
        ID = iD;
        Name = name;
        Level = level;
        ParentID = parentID;
        Children = new HashSet<Hierarchy>();
    }
    public string ID { get; set; }
    public string Name{ get; set; }
    public int Level { get; set; }
    public string ParentID { get; set; }
    public ICollection<Hierarchy> Children { get; set; }
}

public class Program
{
    static Hierarchy CreateTree(IEnumerable<Hierarchy> Nodes)
    {
        var idToNode = Nodes.ToDictionary(n => n.ID, n => n);

        Hierarchy root = null;
        foreach (var n in Nodes)
        {
            if (n.ParentID == null)
            {
                if (root != null)
                {
                    //there are multiple roots in the data
                }
                root = n;
                continue;
            }

            Hierarchy parent = null;
            if (!idToNode.TryGetValue(n.ParentID, out parent))
            {
                //Parent doesn't exist, orphaned entry
            }

            parent.Children.Add(n);

            Console.WriteLine("ReferenceEquals: {0}", Object.ReferenceEquals(parent, root));
        }

        if (root == null)
        {
            //There was no root element
        }
        return root;
    }

    public static void Main()
    {
        Console.WriteLine("Test #1");

        List<Hierarchy> l = new List<Hierarchy>();
        l.Add(new Hierarchy("295152","name1",1,null, null)); // <-root node at the top of the list
        l.Add(new Hierarchy("12345","child1",2,"295152", null));
        l.Add(new Hierarchy("54321","child2",2,"295152", null));
        l.Add(new Hierarchy("44444","child1a",3,"12345", null));
        l.Add(new Hierarchy("33333","child1b",3,"12345", null));
        l.Add(new Hierarchy("22222","child2a",3,"54321", null));
        l.Add(new Hierarchy("22221","child2b",3,"54321", null));
        l.Add(new Hierarchy("22002","child2c",3,"54321", null));
        l.Add(new Hierarchy("20001","child2a2",4,"22222", null));
        l.Add(new Hierarchy("20101","child2b2",4,"22222", null));       

        CreateTree(l);

        Console.WriteLine("\nTest #2");

        l = new List<Hierarchy>();
        l.Add(new Hierarchy("12345","child1",2,"295152", null));
        l.Add(new Hierarchy("54321","child2",2,"295152", null));
        l.Add(new Hierarchy("44444","child1a",3,"12345", null));
        l.Add(new Hierarchy("33333","child1b",3,"12345", null));
        l.Add(new Hierarchy("22222","child2a",3,"54321", null));
        l.Add(new Hierarchy("22221","child2b",3,"54321", null));
        l.Add(new Hierarchy("22002","child2c",3,"54321", null));
        l.Add(new Hierarchy("20001","child2a2",4,"22222", null));
        l.Add(new Hierarchy("20101","child2b2",4,"22222", null));
        l.Add(new Hierarchy("295152","name1",1,null, null)); // <-root node at the bottom of the list
        CreateTree(l);
    }
}
...