我尝试将 except 方法与自定义相等比较器一起使用,但它不起作用。

我的平等比较器:

public class BusinessObjectGuidEqualityComparer<T> : IEqualityComparer<T> where T : BusinessObject
{
    #region IEqualityComparer<T> Members

    /// <summary>
    /// Determines whether the specified objects are equal.
    /// </summary>
    /// <param name="x">The first object of type <paramref name="T"/> to compare.</param>
    /// <param name="y">The second object of type <paramref name="T"/> to compare.</param>
    /// <returns>
    /// <see langword="true"/> If the specified objects are equal; otherwise, <see langword="false"/>.
    /// </returns>
    public bool Equals(T x, T y)
    {
        return (x == null && y == null) || (x != null && y != null && x.Guid.Equals(y.Guid));
    }

    /// <summary>
    /// Returns a hash code for this instance.
    /// </summary>
    /// <param name="obj">The object to get the hash code.</param>
    /// <returns>
    /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
    /// </returns>
    /// <exception cref="T:System.ArgumentNullException">
    /// The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.
    /// </exception>
    public int GetHashCode(T obj)
    {
        if (obj == null)
        {
            throw new ArgumentNullException("obj");
        }

        return obj.GetHashCode();
    }

    #endregion
}

我的除了用法:
BusinessObjectGuidEqualityComparer<Area> comparer = new BusinessObjectGuidEqualityComparer<Area>();
IEnumerable<Area> toRemove = this.Areas.Except(allocatedAreas, comparer);
IEnumerable<Area> toAdd = allocatedAreas.Except(this.Areas, comparer);

奇怪的是,事件我提供我的自定义相等比较器使用默认的比较器,那么我做错了什么?

感谢帮助。

最佳答案

与 Marc 类似,我刚刚测试了这个,一切都被调用得很好,我的猜测是你被 LINQ 延迟执行所捕获,注意我代码中的 ToArray。

注意,在跟踪这个时,我注意到 GetHashCode 永远不会在比较器中的空对象上调用。

请记住,MiscUtil 有一种很棒的方法可以让您内联执行这些操作,请参阅:Can I specify my explicit type comparator inline?

或者您可以将其调整为“除外”:Distinct list of objects based on an arbitrary key in LINQ

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

namespace ConsoleApplication1 {

    public class BusinessObject {
        public Guid Guid { get; set; }
    }

    public class BusinessObjectGuidEqualityComparer<T> : IEqualityComparer<T> where T : BusinessObject {
        #region IEqualityComparer<T> Members

        public bool Equals(T x, T y) {
            return (x == null && y == null) || (x != null && y != null && x.Guid.Equals(y.Guid));
        }

        /// </exception>
        public int GetHashCode(T obj) {
            if (obj == null) {
                throw new ArgumentNullException("obj");
            }

            return obj.GetHashCode();
        }

        #endregion
    }

    class Program {
        static void Main(string[] args) {

            var comparer = new BusinessObjectGuidEqualityComparer<BusinessObject>();

            List<BusinessObject> list1 = new List<BusinessObject>() {
                new BusinessObject() {Guid = Guid.NewGuid()},
                new BusinessObject() {Guid = Guid.NewGuid()}
            };

            List<BusinessObject> list2 = new List<BusinessObject>() {
                new BusinessObject() {Guid = Guid.NewGuid()},
                new BusinessObject() {Guid = Guid.NewGuid()},
                null,
                null,
                list1[0]
            };

            var toRemove = list1.Except(list2, comparer).ToArray();
            var toAdd = list2.Except(list1, comparer).ToArray();

            // toRemove.Length == 1
            // toAdd.Length == 2
            Console.ReadKey();
        }
    }
}

关于c# - Enumerable.Except 不使用我的自定义比较器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1321076/

10-13 08:39