为什么我不能使用这个嵌套的lambda表达式?

时间:2011-10-21 17:27:25

标签: c# lambda

我正在尝试从各种查询中维护一个独特模型列表。不幸的是,我们的模型的equals方法没有定义,所以我不能轻易使用哈希映射。

作为快速修复,我使用了以下代码:

public void AddUnique(
    List<Model> source,
    List<Model> result)
{
    if (result != null)
    {
        if (result.Count > 0
            && source != null
            && source.Count > 0)
        {
            source.RemoveAll(
                s => result.Contains(
                    r => r.ID == s.ID));
        }

        result.AddRange(source);
    }
}

不幸的是,这不起作用。当我逐步完成代码时,我发现即使我已经检查过以确保Model和{{1}中至少有一个ID具有相同的source },result行不会更改RemoveAll(Predicate<Model>)中的项目数。我错过了什么?

4 个答案:

答案 0 :(得分:10)

上面的代码甚至不应该编译,因为Contains需要Model,而不是谓词。

您可以使用Any()代替:

source.RemoveAll(s => result.Any(r => r.ID == s.ID));

这将正确删除源中的项目。

答案 1 :(得分:1)

我可能会选择以不同的方式解决问题。

你说你在课堂上没有合适的平等实现。也许你不能改变它。但是,您可以定义IEqualityComparer<Model>实现,该实现允许您指定实际Equals类本身外部的相应GetHashCodeModel实现。

var comparer = new ModelComparer();
var addableModels = newSourceOfModels.Except(modelsThatAlreadyExist, comparer);
// you can then add the result to the existing

您可以将比较器定义为

class ModelComparer : IEqualityComparer<Model>
{
     public bool Equals(Model x, Model y)
     {
         // validations omitted
         return x.ID == y.ID;
     }

     public int GetHashCode(Model m)
     {
         return m.ID.GetHashCode();
     }
}

答案 2 :(得分:0)

source.RemoveAll(source.Where(result.Select(r => r.ID).Contains(source.Select(s => s.ID))));

此语句的目标是制作两个ID枚举,一个用于源,一个用于结果。然后,它将返回两个枚举中每个元素的where语句的true。然后它将删除任何返回true的元素。

答案 3 :(得分:0)

您的代码正在删除两个列表中相同的所有模型,而不是那些具有相同 ID 的模型。除非它们实际上是模型的相同实例,否则它将无法像您期望的那样工作。

有时我会将这些扩展方法用于此类事情:

public static class CollectionHelper
{
    public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> selector)
    {
        var itemsToRemove = list.Where(selector).ToList();
        foreach (var item in itemsToRemove)
        {
            list.Remove(item);
        }
    }

    public static void RemoveWhere<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<KeyValuePair<TKey, TValue>, bool> selector)
    {
        var itemsToRemove = dictionary.Where(selector).ToList();
        foreach (var item in itemsToRemove)
        {
            dictionary.Remove(item);
        }
    }
}