Except() - 带有 CustomPropertyEqualityComparer 和 NO Distinct 的方法

Except()-Method with CustomPropertyEqualityComparer and NO Distinct

我使用自己的 CustomPropertyEqualityComparer 通过自定义属性动态比较对象列表。

这是 CustomPropertyEqualityComparer:

public class CustomPropertyEqualityComparer<T> : IEqualityComparer<T> where T : class
{
    public PropertyInfo[] _PropertyInfos;

    /// <summary>
    /// Creates a new instance of PropertyComparer.
    /// </summary>
    /// <param name="propertyName">The name of the property on type T 
    /// to perform the comparison on.</param>
    public CustomPropertyEqualityComparer(params string[] propertyName)
    {
        _PropertyInfos = new PropertyInfo[propertyName.Length];

        //store a reference to the property info object for use during the comparison
        for (int i = 0; i < propertyName.Length; i++)
        {
            _PropertyInfos[i] = typeof(T).GetProperty(propertyName[i], BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
            if (_PropertyInfos == null)
            {
                throw new ArgumentException(string.Format("{0} is not a property of type {1}.", propertyName, typeof(T)));
            }
        }
    }

    public bool Equals(T x, T y)
    {
        foreach (PropertyInfo propInf in _PropertyInfos)
        {
            if (propInf != null)
            {
                //get the current value of the comparison property of x and of y
                object xValue = propInf.GetValue(x, null);
                object yValue = propInf.GetValue(y, null);

                //if the xValue is null then we consider them equal if and only if yValue is null
                if (xValue != yValue && (xValue == null || !xValue.Equals(yValue)))
                {
                    return false;
                }    
            }               

        }
        return true;
    }

    public int GetHashCode(T obj)
    {
        int HashCode = 0;

        foreach (var p in _PropertyInfos)
        {
            if (p != null)
            {
                HashCode += p.GetHashCode();    
            }                
        }

        return HashCode;
    }
}

我是这样使用的:

List<T> ListNewObj = ListObj2.Except(ListObj1, CustomPropertyComparer).ToList();

假设 ListObj2 有两个相同的项目,ListObj1 是空的,ListNewObj 将只包含 ListObj2 中的一个项目,但我希望它们都在 ListNewObj 中,

问题是,似乎在 Except() 和 Intersect() 之后自动跟随一个 Distinct(),但我如何避免这种情况?

The Problem is, that it seems that after a Except() and Intersect() a Distinct() follows automatically

不是真的。这只是意味着它是一个基于集合的操作——所以结果永远不会包含两个相等的(在你的平等比较下)结果。如果您查看我的 sample implementation,您会发现它不一定是两步操作。不幸的是,它没有被非常清楚地记录下来。

避免这种情况的最简单方法就是自己执行过滤:

var excludedSet = new HashSet<T>(ListObj1, CustomPropertyComparer);
var result = ListObj2.Where(x => !excludedSet.Contains(x))
                     .ToList();