Как объяснил emaster70, версия Deferred
пересчитывает коллекцию even
для каждого вызова even.Contains
. Это делает его очень быстро ухудшаться при более высоких значениях limit
.
Версия Immediate
лучше, и если вы также сделаете коллекцию all
незамедлительной, например:
var all = Range(limit).ToArray();
становится примерно в три раза быстрее.
Однако метод Contains
для массива является операцией O (n), поэтому он также плохо масштабируется. Если условие является равенством, вы должны использовать объединение, а не искать каждое значение, используя Contains
.
Если вам нужно выполнить поиск, вы должны использовать HashSet
вместо массива, так как метод Contains
для этого является операцией O (1).
Для limit
из 10000 это в 100 раз быстрее, чем Immediate
версия:
public void Joined() {
var all = Range(limit);
var even = from e in EvenRange(limit) join a in all on e equals a select e;
var evenSet = new HashSet<int>(even);
var odd = from o in OddRange(limit) where !evenSet.Contains(o) select o;
var query = from q in odd select q;
foreach (var i in query) { var j = i + 1; }
}