Я надеюсь, что кто-то может пролить свет на (для меня) неожиданную поведенческую разницу между двумя (с точки зрения результата) равными запросами.
Маленькая программа может стоить тысячи слов, так что вот:
static void Main(string[] args)
{
var l1 = new List<int> { 1, 2, 3 };
var l2 = new List<int> { 2, 3, 4 };
var q1 = // or var q1 = l1.Join(l2, i => i, j => j, (i, j) => i);
from i in l1
join j in l2
on i equals j
select i;
var q2 = //or var q2 = l1.SelectMany(i => l2.Where(j => i == j));
from i in l1
from j in l2
where i == j
select i;
var a1 = q1.ToList(); // 2 and 3, as expected
var a2 = q2.ToList(); // 2 and 3, as expected
l2.Remove(2);
var b1 = q1.ToList(); // only 3, as expected
var b2 = q2.ToList(); // only 3, as expected
// now here goes, lets replace l2 alltogether.
// Afterwards, I expected the same result as q1 delivered...
l2 = new List<int> { 2, 3, 4 };
var c1 = q1.ToList(); // only 3 ? Still using the previous reference to l2 ?
var c2 = q2.ToList(); // 2 and 3, as expected
}
Теперь я знаю, что Join внутренне использует класс поиска для оптимизации производительности, и без особых знаний, я предполагаю, что сочетание этого с захваченными переменными может вызвать такое поведение, но сказать, что я действительно это понимаю, нет: - )
Это пример того, что Джоэл называет «дырявой абстракцией»?
Ура,
Bart