Проблема в том, что перечисление Select
выполняется не сразу, а с задержкой. Это означает, что каждый раз, когда вы обращаетесь к / 1002 *, возвращенному методом Select()
, вы получаете новый список fre sh. Но это также означает, что вы постоянно создаете новые Domino
объекты. И поскольку вы не перезаписываете метод Equals()
, каждый из этих Domino
объектов будет отличаться, даже если они имеют одинаковые значения.
Чтобы показать проблему, проверьте следующий код:
private class Foobar {
private readonly int value;
public Foobar(int v) {
Console.WriteLine("## CONSTRUCTOR ## Foobar object created with value: "+v);
this.value = v;
}
public override string ToString() {
return "Foobar("+this.value+")";
}
}
public static void Main(string[] args) {
int[] numbers = new [] { 1, 5};
IEnumerable<Foobar> range = numbers.Select(i => new Foobar(i));
Console.WriteLine(range.Count());
foreach (Foobar entry in range) {
Console.WriteLine("Build an enumerable without "+entry);
IEnumerable<Foobar> remaining = range.Where(it => it != entry);
Console.WriteLine("The length of the remaining: "+remaining.Count());
foreach (Foobar remainingEntry in remaining) {
Console.WriteLine("Entry of remaining: "+remainingEntry);
}
}
}
Когда вы запустите этот код, вы получите следующий вывод:
## CONSTRUCTOR ## Foobar object created with value: 1
## CONSTRUCTOR ## Foobar object created with value: 5
2
## CONSTRUCTOR ## Foobar object created with value: 1
Build an enumerable without Foobar(1)
## CONSTRUCTOR ## Foobar object created with value: 1
## CONSTRUCTOR ## Foobar object created with value: 5
The length of the remaining: 2
## CONSTRUCTOR ## Foobar object created with value: 1
Entry of remaining: Foobar(1)
## CONSTRUCTOR ## Foobar object created with value: 5
Entry of remaining: Foobar(5)
## CONSTRUCTOR ## Foobar object created with value: 5
Build an enumerable without Foobar(5)
## CONSTRUCTOR ## Foobar object created with value: 1
## CONSTRUCTOR ## Foobar object created with value: 5
The length of the remaining: 2
## CONSTRUCTOR ## Foobar object created with value: 1
Entry of remaining: Foobar(1)
## CONSTRUCTOR ## Foobar object created with value: 5
Entry of remaining: Foobar(5)
Как видите, конструктор слишком часто вызывается . Каждый раз, когда кто-то использует IEnumerable
из вызова Select()
, он снова генерирует перечислимый список, чтобы он не мешал другим параллельным итерациям на тех же данных. Однако, поскольку вы создаете новые объекты внутри оператора Select()
, вы будете получать новые объекты для каждого создания IEnumerable
из Select()
.
Как вы уже заметили, для решения проблемы вы используете что-то например, ToList()
и один раз для оценки / создания Domino
объектов. При одном вызове ToList()
выходные изменения изменяются следующим образом:
## CONSTRUCTOR ## Foobar object created with value: 1
## CONSTRUCTOR ## Foobar object created with value: 5
2
Build an enumerable without Foobar(1)
The length of the remaining: 1
Entry of remaining: Foobar(5)
Build an enumerable without Foobar(5)
The length of the remaining: 1
Entry of remaining: Foobar(1)
Видите ли, создаются только два объекта, и !=
будет работать, как и ожидалось, поскольку существуют только эти два объекта.