File: System\Xml\Linq\XNodeEqualityComparer.cs
Web Access
Project: src\src\libraries\System.Private.Xml.Linq\src\System.Private.Xml.Linq.csproj (System.Private.Xml.Linq)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
 
using IEqualityComparer = System.Collections.IEqualityComparer;
 
namespace System.Xml.Linq
{
    /// <summary>
    /// Contains functionality to compare nodes for value equality.
    /// This class cannot be inherited.
    /// </summary>
    public sealed class XNodeEqualityComparer :
        IEqualityComparer,
        IEqualityComparer<XNode>
    {
        /// <summary>
        /// Compares the values of two nodes.
        /// </summary>
        /// <param name="x">The first node to compare.</param>
        /// <param name="y">The second node to compare.</param>
        /// <returns>true if the nodes are equal, false otherwise.</returns>
        /// <remarks>
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two <see cref="XNode"/>s of different types are never equal. Two
        /// <see cref="XText"/> nodes are equal if they contain the same text. Two
        /// <see cref="XElement"/> nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of pairwise equal content nodes.
        /// Two <see cref="XDocument"/>s are equal if their root nodes are equal. Two
        /// <see cref="XComment"/> nodes are equal if they contain the same comment text.
        /// Two <see cref="XProcessingInstruction"/> nodes are equal if they have the same
        /// target and data. Two <see cref="XDocumentType"/> nodes are equal if the have the
        /// same name, public id, system id, and internal subset.
        /// </remarks>
        public bool Equals(XNode? x, XNode? y)
        {
            return XNode.DeepEquals(x, y);
        }
 
        /// <summary>
        /// Returns a hash code based on an <see cref="XNode"/> objects value.
        /// </summary>
        /// <param name="obj">The node to hash.</param>
        /// <returns>A value-based hash code for the node.</returns>
        /// <remarks>
        /// The <see cref="XNode"/> class's implementation of <see cref="object.GetHashCode"/>
        /// is based on the referential identity of the node. This method computes a
        /// hash code based on the value of the node.
        /// </remarks>
        public int GetHashCode(XNode obj)
        {
            return obj != null ? obj.GetDeepHashCode() : 0;
        }
 
        /// <summary>
        /// Compares the values of two nodes.
        /// </summary>
        /// <param name="x">The first node to compare.</param>
        /// <param name="y">The second node to compare.</param>
        /// <returns>true if the nodes are equal, false otherwise.</returns>
        /// <remarks>
        /// A null node is equal to another null node but unequal to a non-null
        /// node. Two <see cref="XNode"/>s of different types are never equal. Two
        /// <see cref="XText"/> nodes are equal if they contain the same text. Two
        /// <see cref="XElement"/> nodes are equal if they have the same tag name, the same
        /// set of attributes with the same values, and, ignoring comments and processing
        /// instructions, contain two equal length sequences of pairwise equal content nodes.
        /// Two <see cref="XDocument"/>s are equal if their root nodes are equal. Two
        /// <see cref="XComment"/> nodes are equal if they contain the same comment text.
        /// Two <see cref="XProcessingInstruction"/> nodes are equal if they have the same
        /// target and data. Two <see cref="XDocumentType"/> nodes are equal if the have the
        /// same name, public id, system id, and internal subset.
        /// </remarks>
        bool IEqualityComparer.Equals(object? x, object? y)
        {
            XNode? n1 = x as XNode;
            if (n1 == null && x != null) throw new ArgumentException(SR.Format(SR.Argument_MustBeDerivedFrom, typeof(XNode)), nameof(x));
            XNode? n2 = y as XNode;
            if (n2 == null && y != null) throw new ArgumentException(SR.Format(SR.Argument_MustBeDerivedFrom, typeof(XNode)), nameof(y));
            return Equals(n1, n2);
        }
 
        /// <summary>
        /// Returns a hash code based on a node's value.
        /// </summary>
        /// <param name="obj">The node to hash.</param>
        /// <returns>A value-based hash code for the node.</returns>
        /// <remarks>
        /// The <see cref="XNode"/> class's implementation of <see cref="object.GetHashCode"/>
        /// is based on the referential identity of the node. This method computes a
        /// hash code based on the value of the node.
        /// </remarks>
        int IEqualityComparer.GetHashCode(object obj)
        {
            XNode? n = obj as XNode;
            if (n == null && obj != null) throw new ArgumentException(SR.Format(SR.Argument_MustBeDerivedFrom, typeof(XNode)), nameof(obj));
            return GetHashCode(n!);
        }
    }
}