在我的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可能还有另一种方法吗?
提前致谢,
弗兰克
答案 0 :(得分:15)
您不必编写Contains方法,Linq的Any方法已经这样做了:
if (!_collection.Any(p => p.Name == name2CheckAgainst))
如果要使用Lambda,则必须更改Contains方法的原型以接受Lambda(lambda只是编写匿名函数的另一种方法):
private bool CollectionContainsElement(Func<myInterface, bool> lambda)
{
foreach (myInterface item in _collection)
if (lambda(item))
return true;
return false;
}
在这里使用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兼容扩展方法