在ObservableCollection上使用Lambda表达式

时间:2011-11-28 16:41:30

标签: c# collections lambda contains

在我的Silverlight 4应用程序中,我有一个ObservableCollection,它由一个类的对象组成,并由一个接口定义:

interface myInterface()
{
  string Name { get; set; }
  string Value { get; set; }
} 

class myClass() : myInterface
{
  ...
}

ObservableCollection<myInterface> _collection;

在向集合添加新元素之前,我想确保Name-Property在当前集合元素中不存在。 由于我无法使用contains,我目前遍历所有元素并手动检查每个元素。

private bool CollectionContainsElement(string name2CheckAgainst)
{
  foreach (myInterface item in _collection)
    if (item.Name.Equals(name2CheckAgainst))
      return true;

  return false;
}

我已经读过这也可以通过Lambda Expression实现,所以我写了以下内容:

if (!_collection.Contains(p => p.Name == name2CheckAgainst))
{
  ...

但现在我收到一个错误,说“lambda表达式无法转换为Type”myInterface“,因为它不是委托类型”。 (措辞可能有所不同,因为我将其翻译成德文版本)

我不确定我需要改变什么才能让它发挥作用。 using System.Linq;包括在内。第二个问题(或者可能是主要问题):我已经读过,运行时从O(1)变为Contains() - 方法变为O(n) - 这不比我当前的检查快。那么将它改为使用lambda甚至是否有意义?最后,在我的班级中检查现有的Name-Property可能还有另一种方法吗?

提前致谢,
弗兰克

3 个答案:

答案 0 :(得分:15)

  1. 您不必编写Contains方法,Linq的Any方法已经这样做了:

    if (!_collection.Any(p => p.Name == name2CheckAgainst))
    
  2. 如果要使用Lambda,则必须更改Contains方法的原型以接受Lambda(lambda只是编写匿名函数的另一种方法):

    private bool CollectionContainsElement(Func<myInterface, bool> lambda)
    {
      foreach (myInterface item in _collection)
        if (lambda(item))
          return true;
    
      return false;
    }
    
  3. 在这里使用lambda不会改变函数的复杂性,在两种情况下都是O(n)。所以这只是一个偏好问题。

答案 1 :(得分:2)

您可以使用Linq Any() method。哪个可以这样使用:

if (!_collection.Any(p => p.Name == name2CheckAgainst))
{
}

contains方法是O(1)的原因是它将你的集合加载到HashTable(或类似的)中并使用哈希代码(后跟对Equals的调用)来检查元素是否存在。

答案 2 :(得分:1)

包含不是LINQ扩展,因此您不能使用lambda表达式。它旨在检查列表中是否存在对象

正如其他人所说,Any是一种等效的lambda-expression兼容扩展方法