It’s because the ForEach method doesn’t use the enumerator, it loops through the items with a for loop:
public void ForEach(Action<T> action)
{
if (action == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
for (int i = 0; i < this._size; i++)
{
action(this._items[i]);
}
}
(code obtained with JustDecompile)
Since the enumerator is not used, it never checks if the list has changed, and the end condition of the for loop is never reached because _size is increased at every iteration.