/// <inheritdoc /> public override ITreeNode <T> Union(ITreeNode <T> other, DEquality <ITreeNode <T> > equality, DMerge <T> merge) { // if not equal, return null if (!equality(this, other)) { return(null); } // since values are equal, if they both have no children, return node with value if (ChildCount == 0 && other.ChildCount == 0) { return(new UniqueChildrenTreeNode <T>(merge(Value, other.Value))); } // return copy of node with children if only 1 has children if (ChildCount > 0 && other.ChildCount == 0) { return(Copy()); } if (other.ChildCount > 0 && ChildCount == 0) { return(other.Copy()); } // set up the union tree for recursive calculation UniqueChildrenTreeNode <T> unionTree = new UniqueChildrenTreeNode <T>(merge(Value, other.Value)); // sort out children in both that have no equivalent in other // perform a union on any nodes that match List <ITreeNode <T> > otherNodesNotInOriginal = new List <ITreeNode <T> >(other.Children); List <ITreeNode <T> > originalNodesNotInOther = new List <ITreeNode <T> >(); foreach (ITreeNode <T> child in Children) { ITreeNode <T> matchingOtherNode = otherNodesNotInOriginal.Find(n => equality(n, child)); if (matchingOtherNode == default(ITreeNode <T>)) { originalNodesNotInOther.Add(child); } else { UniqueChildrenTreeNode <T> newUnion = child.Union(matchingOtherNode) as UniqueChildrenTreeNode <T>; if (newUnion == null) { continue; } // add union of matching nodes to tree UnsafeAddChild(unionTree, newUnion); otherNodesNotInOriginal.Remove(matchingOtherNode); } } // copy other nodes missing from original foreach (ITreeNode <T> node in otherNodesNotInOriginal) { node.Copy(unionTree); } // copy original nodes missing from other foreach (ITreeNode <T> node in originalNodesNotInOther) { node.Copy(unionTree); } return(unionTree); }