Использование лямбда-выражения в ObservableCollection - PullRequest
5 голосов
/ 28 ноября 2011

в моем приложении Silverlight 4 у меня есть ObservableCollection, которая состоит из объектов класса и определяется интерфейсом:

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

class myClass() : myInterface
{
  ...
}

ObservableCollection<myInterface> _collection;

Прежде чем добавить новый элемент в коллекцию, я хочу убедиться,, что Name-Property еще не существует в текущих элементах коллекции.Поскольку я не могу работать с содержимым, я в настоящее время перебираю все элементы и проверяю каждый элемент вручную.

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

  return false;
}

Я прочитал, что этого также можно добиться с помощью лямбда-выражения, поэтому я написал следующее:

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

Но теперь я получаю сообщение об ошибке, в котором говорится, что «лямбда-выражение не может быть преобразовано в тип« myInterface », поскольку он не является типом делегата».(Формулировка может отличаться, поскольку я перевел ее с немецкой версии)

Я не уверен, что мне нужно изменить, чтобы это работало.using System.Linq; включено.И второй вопрос (или, может быть, основной вопрос): я прочитал, что время выполнения меняется с O (1) для метода Contains () - на O (n) - что не быстрее, чем моя текущая проверка.Так есть ли смысл менять его на использование лямбды?И, наконец, есть ли другой способ проверки существующего Name-свойства в моем классе?

Заранее спасибо,
Frank

Ответы [ 3 ]

15 голосов
/ 28 ноября 2011
  1. Вам не нужно писать метод Contains, метод Any Linq уже делает это:

    if (!_collection.Any(p => p.Name == name2CheckAgainst))
    
  2. Если вы хотите использоватьлямбда, вы должны изменить прототип вашего метода Contains, чтобы он принимал лямбду (лямбда - просто альтернативный способ написания анонимной функции):

    private bool CollectionContainsElement(Func<myInterface, bool> lambda)
    {
      foreach (myInterface item in _collection)
        if (lambda(item))
          return true;
    
      return false;
    }
    
  3. Использование лямбдыздесь не меняет сложность вашей функции, это O (n) в обоих случаях.Так что это просто вопрос предпочтений.

2 голосов
/ 28 ноября 2011

Вы можете использовать Linq Any () метод . Который можно использовать так:

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

Причина, по которой метод содержимого является O (1), заключается в том, что под обложками он загружает вашу коллекцию в HashTable (или аналогичный) и использует хеш-код (сопровождаемый вызовом Equals), чтобы проверить, присутствует ли элемент ,

1 голос
/ 28 ноября 2011

Contains не является расширением LINQ, поэтому с ним нельзя использовать лямбда-выражения.Он был разработан для проверки наличия объекта в списке.

Как уже говорили другие, Any является эквивалентным лямбда-выражением совместимым методом расширения

...