c#Linq除了不返回不同值的列表

时间:2014-07-02 20:25:55

标签: c# linq

我试图在两个列表中找到差异。列表," y"与list" x"相比,应该有1个唯一值。但是,除此之外,不会返回差异。 ,"差异"列表的计数总是等于0.

List<EtaNotificationUser> etaNotifications = GetAllNotificationsByCompanyIDAndUserID(PrevSelectedCompany.cmp_ID);
IEnumerable<string> x = etaNotifications.OfType<string>();
IEnumerable<string> y = EmailList.OfType<string>();

IEnumerable<string> differences = x.Except(y,  new StringLengthEqualityComparer()).ToList();

   foreach(string diff in differences)
                {
                    addDiffs.Add(diff);
                }

在阅读了帖子上的几篇文章和文章后,我创建了一个自定义比较器。比较器查看字符串长度(保持它的测试简单)并获得Hashcode,因为这是两个不同类型的对象(即使我将它们的类型转换为字符串),我认为它可能是问题。

class StringLengthEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Length == y.Length;
    }

    public int GetHashCode(string obj)
    {
        return obj.Length;
    }
}

这是我第一次使用Except。听起来像是比较两个列表的一种优秀的,优化的方式,但我不能让它工作。

更新

X - 应该从数据库中保存电子邮件地址。 GetAllNotificationsByCompanyIDAndUserID - 从数据库中返回电子邮件值。 Y - 应该在UI网格中保存所有电子邮件地址。

我要做的是检测是否已将新电子邮件添加到网格中。因此,此时X将具有过去条目中保存的值。 Y将有用户添加的任何新电子邮件地址,但尚未保存。

我已经确认这一切都正常。

2 个答案:

答案 0 :(得分:4)

问题在于:

IEnumerable<string> x = etaNotifications.OfType<string>();

etaNotificationsList<EtaNotificationUser>,由于stringstring,所以sealed都不能为OfTypex返回属于给定类型的所有实例 - 它不会将每个成员“转换”为该类型。

所以IEnumerable<string> x = etaNotifications.Select(e => e.ToString()); 永远是空的。

也许你想要:

EtaNotificationUser

如果ToString已覆盖IEnumerable<string> x = etaNotifications.Select(e => e.EmailAddress); ,则会为您提供要比较的值。如果要比较的值在属性中,则可以使用:

y

或其他一些财产。

您可能需要针对EmailList执行类似操作(除非List<string>已经是{{1}}我怀疑)。

答案 1 :(得分:1)

假设你已经验证了你的两个可用数据x和y实际上包含了你期望它们的字符串,我相信你的问题在于你的字符串比较器。根据文档,Enumerable.Except“产生两个序列的集合差异。集合差异是第一个序列的成员,不出现在第二个序列中。”但是你的相等比较器将所有字符串等同于 length 。因此,如果第一个序列中的字符串恰好与第二个序列中的字符串具有相同的长度,则使用比较器将不会发现它不同。

更新:是的,我刚试过它:

public class StringLengthEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.Length == y.Length;
    }

    public int GetHashCode(string obj)
    {
        return obj.Length;
    }
}


        string [] array1 = new string [] { "foo", "bar", "yup" };
        string[] array2 = new string[] { "dll" };
        int diffCount;

        diffCount = 0;
        foreach (var diff in array1.Except(array2, new StringLengthEqualityComparer()))
        {
            diffCount++;
        }

        Debug.Assert(diffCount == 0); // No assert.

        diffCount = 0;
        foreach (var diff in array1.Except(array2))
        {
            diffCount++;
        }

        Debug.Assert(diffCount == 0); // Assert b/c diffCount == 3.

自定义比较器没有断言但有标准。