Задать вопрос
@izjalvovich

C#: почему foreach над массивом структур быстрее, чем for?

Добрый день. Имеется следующий тест, где проверяется скорость перебора массива структур и работы с ними с передачей по значению и по ссылке:
[MemoryDiagnoser]
public class Tests
{
  private QS[] _qs;

  public Tests()
  {
    _qs = null!;
  }

  [GlobalSetup]
  public void Init()
  {
    _qs = new QS[100000];
    for (int i = 0; i < 100000; i++) {
      _qs[i] = new QS() { Length = i, Start = i, Source = string.Empty };
    }
  }

  [Benchmark(Baseline = true)]
  [MinIterationCount(25)]
  [InvocationCount(10000)]
  public bool Foreach()
  {
    foreach (var qs in _qs)
      if (ByValue(qs))
        return true;
    return false;
  }

  [Benchmark]
  [MinIterationCount(25)]
  [InvocationCount(10000)]
  public bool ForeachIn()
  {
    foreach (var qs in _qs)
      if (ByRef(in qs))
        return true;
    return false;
  }

  [Benchmark]
  [MinIterationCount(25)]
  [InvocationCount(10000)]
  public bool For()
  {
    for (var i = 0; i < _qs.Length; i++)
      if (ByValue(_qs[i]))
        return true;
    return false;
  }

  [Benchmark]
  [MinIterationCount(25)]
  [InvocationCount(10000)]
  public bool ForRef()
  {
    for (var i = 0; i < _qs.Length; i++) {
      if (ByRef(ref _qs[i]))
        return true;
    }
    return false;
  }

  private bool ByValue(QS qs)
  {
    return qs.Start != qs.Length;
  }

  private bool ByRef(ref readonly QS qs)
  {
    return qs.Start != qs.Length;
  }
}

public struct QS
{
  public int Start { get; set; }

  public int Length { get; set; }

  public string? Source { get; set; }
}

Результат:
67bd7663cbc69186184020.jpeg

Почему foreach отрабатывает быстрее? К тому же видно, что передача по ссылке в foreach даёт прирост скорости, в то время как в for это никак не повлияло на результат.
  • Вопрос задан
  • 101 просмотр
Подписаться 2 Простой 4 комментария
Пригласить эксперта
Ответы на вопрос 2
iamkisly
@iamkisly
Собираю админки на dotnet и extjs
Не буду умничать, что foreach это синтаксический сахар над while и IEnumerable / IEnumerator, и как минимум нет проверки условий, вы просто ловите эксепшн, когда нет следущего элемента )) В общем обычно в таких вопросах рекомендуется смотреть в генерируемый IL, тогда будет все понятно
Ответ написан
@Csus4
Возможно, что это связано с проверкой границ массива в случае с for, в то время как foreach использует итератор, который позволяет не делать эту проверку.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы