2010-07-19 8 views
2

Этот код работает, но неэффективен, потому что он дважды ищет словарь ignored. Как я могу использовать метод словаря TryGetValue() в операторе LINQ, чтобы сделать его более эффективным?Использование TryGetValue() в LINQ?

IDictionary<int, DateTime> records = ... 

IDictionary<int, ISet<DateTime>> ignored = ... 

var result = from r in records 
      where !ignored.ContainsKey(r.Key) || 
      !ignored[r.Key].Contains(r.Value) 
      select r; 

Проблема заключается в том, что я не уверен, как объявить переменную в инструкции LINQ для использования для параметра out.

ответ

1

Вы должны объявить переменную out перед запросом:

ISet<DateTime> s = null; 
var result = from r in records 
      where !ignored.TryGetValue(r.Key, out s) 
       || !s.Contains(r.Value) 
      select r; 

Будьте осторожны побочных эффектов, если запрос не вычисляется, пока позже, хотя ...

+0

Это работает. Я предполагаю, что вы оцениваете его, пока переменная все еще находится в области видимости, и не пытайтесь использовать ее с параллельным LINQ. –

+0

@Joe, точно ... это имело бы непредсказуемые эффекты –

1

Использование внешней переменной, вам не нужно беспокоиться об этом, выходя из сферы действия, потому что выражение LINQ - это закрытие, которое будет поддерживать его. Однако, чтобы избежать каких-либо конфликтов, вы могли бы поставить переменную и выражение в функции:

public IEnumerable GetRecordQuery() { 
    ISet<DateTime> s = null; 
    return from r in records 
      ... 
} 

... 

var results = GetRecordQuery(); 

Таким образом, только запрос имеет доступ к переменной s, а также любые другие вопросы (возвращенное из отдельных вызовов GetRecordQuery) будет каждый из них имеет свой экземпляр переменной.