Я придумал другой подход. Он хорошо использует итератор while
, но результаты кэшируются в памяти, как обычный LINQ, до тех пор, пока они не понадобятся.
Вот код.
public IEnumerable<IEnumerable<T>> Paginate<T>(this IEnumerable<T> source, int pageSize)
{
List<IEnumerable<T>> pages = new List<IEnumerable<T>>();
int skipCount = 0;
while (skipCount * pageSize < source.Count) {
pages.Add(source.Skip(skipCount * pageSize).Take(pageSize));
skipCount += 1;
}
return pages;
}
На 50 лет опоздали, но эй.
Нет, полезны, если вы набираете ассемблерный код вручную. Если бы вам пришлось удалить код, вы не смогли бы использовать старые коды операций.
Аналогично, вы могли бы вставить новый код, перезаписав некоторый код операции, и перейти в другое место. Там вы помещаете перезаписанные коды операций и вставляете свой новый код. Когда будешь готов, ты прыгаешь назад.
Иногда приходилось использовать доступные инструменты. В некоторых случаях это был простой редактор машинного кода.
В наши дни с компиляторами техника больше не имеет никакого смысла.
В одном процессоре, с которым я работал недавно (четыре года), использовалось NOP, чтобы убедиться, что предыдущая операция завершилась до начала следующей операции. Например:
загрузить значение в регистр (занимает 8 циклов) nop 8 добавить 1 в регистр
Это обеспечило правильное значение регистра перед операцией добавления.
Другое использование заключалось в заполнении исполнительных единиц, таких как векторы прерывания, которые должны были иметь определенный размер (32 байта), потому что адрес для вектора 0 было, скажем, 0, для вектора 1 0x20 и так далее, поэтому компилятор при необходимости вставлял NOP.