Nano Hash - криптовалюты, майнинг, программирование

С# эквивалентен функциям Delphi High() и Low() для массивов, поддерживающих производительность?

В Delphi есть функции Low() и High(), которые возвращают самое нижнее и самое верхнее измерения индекса для массива. Это помогает устранить подверженные ошибкам циклы for для итерации массива, который может стать жертвой коварной ошибки границы массива +1/-1, например, используя ‹=, когда вы имели в виду для условия завершения в инструкции for loop.

Вот пример для функций Low/High (в Delphi):

for i := Low(ary) to High(ary) do

Сейчас я использую простой оператор for loop в C#:

for (int i = 0; i < ary.Length; i++)

Я знаю, что существует метод Array GetDimension(N), но у него есть свои недостатки, поскольку я могу внести ошибку, случайно используя неправильный индекс измерения. Я думаю, что мог бы что-то сделать с перечислителями, но я беспокоюсь, что при сканировании большого массива производительность будет значительно снижаться по сравнению с использованием цикла for. Есть ли эквивалент High/Low в C#?


Ответы:


1

Эквивалентными встроенным функциям low(ary) и high(ary) в C# являются, соответственно, 0 и ary.Length-1. Это связано с тем, что массивы C# отсчитываются от нуля. Я не вижу причин, по которым свойство Length массива должно иметь характеристики производительности, отличные от high() в Delphi.

С точки зрения производительности, большая разница между циклом Pascal for и циклом, используемым языками, производными от C, касается оценки теста завершения. Рассмотрим классический цикл Pascal for:

for i := 0 to GetCount()-1 do
  ....

В цикле Pascal for GetCount() вычисляется только один раз, в начале цикла.

Теперь рассмотрим эквивалент на языке, производном от C:

for (int i=0; i<GetCount(); i++)
  ....

В этом цикле GetCount() оценивается каждый раз в цикле. Таким образом, в таком языке, как C#, вам понадобится локальная переменная, чтобы избежать повторного вызова этой функции.

int N = GetCount();
for (int i=0; i<N; i++)
  ....

В случае массива, если бы оптимизатор мог быть уверен, что ary.Length не изменился во время цикла, тогда код мог бы быть оптимизирован компилятором. Лично я не знаю, делает ли это оптимизатор C#, но дополнительную информацию можно найти в комментариях.

Прежде чем вы начнете переписывать свои циклы, чтобы использовать локальные переменные, содержащие длину массива, проверьте, имеет ли это какое-то значение. Почти наверняка не будет. Разница между паскальскими и C-подобными циклами for, которую я описал выше, вероятно, более существенна в семантическом плане, чем в производительности.


Я особенно завидую языку D. Здесь вы можете использовать цикл foreach, который представляет каждый элемент массива как ссылку и, таким образом, позволяет изменять содержимое массива:

void IncArray(int[] array, int increment) {
    foreach (ref e; array) {
        e += increment;
    }
}    
24.03.2013
  • выражение, которое я разместил ранее, работает в непосредственном окне отладчика при отладке кода С#, но выдает InvalidCastException, если вы попробуете его в исходном коде компиляции С#... интересно 24.03.2013
  • @ 280Z28 Это интересное любопытство, я согласен. Но возможно здесь не по теме. 24.03.2013
  • Если бы это было разрешено в C#, то вы определенно могли бы создать массив, который не использует [0, Length) в качестве границ. Вы по-прежнему можете создать такой массив в C#, но он будет иметь тип IList<byte> вместо byte[]. 24.03.2013
  • Ага. Я добавил ссылку на документы MSDN для массивов C#, чтобы защититься от ваших комментариев! ;-) 24.03.2013
  • Документация, на которую вы ссылаетесь, верна для byte[], но не для byte[,] (или других многомерных массивов). В C# byte[,] не нужно индексировать с [0, 0]. 24.03.2013
  • @ 280Z28 Если вы считаете, что документация MS неверна, сообщите им о проблеме. Подозреваю, что мы говорим о разных вещах. Я говорю о массивах языка С#. Я думаю, вы говорите о классе .net Array. Я понимаю, что последний используется для реализации первого. 24.03.2013
  • Оптимизатор .NET оптимизирует for (int i = 0; i < arr.Length; i++) только в том случае, если arr является локальной переменной. Если это поле, оптимизация не может быть выполнена (поскольку другой метод может изменить arr так, чтобы он указывал на другой объект массива). 24.03.2013

  • 2

    В C# нижняя граница всегда равна нулю, поэтому эквивалентом Low(ary) является просто 0.

    Для одномерного массива эквивалентом High(ary) является ary.Length - 1. (Для многомерных массивов вам все равно потребуется более одного цикла.)

    24.03.2013

    3

    Можете ли вы вместо этого просто использовать оператор foreach? нравится

    foreach(int i in ary)
    {
    . . .
    }
    
    24.03.2013
  • Мне часто приходится изменять элементы массива, а переменная итерации оператора foreach не подлежит изменению. 24.03.2013
  • @RobertOschler Вероятно, следует указать в вопросе. 24.03.2013

  • 4

    [Граница (внутреннее измерение)]

    Эти граничные функции обеспечивают начальную и конечную точки для указанного пользователем измерения любого массива. Второе измерение будет отмечено единицей вместо нуля и так далее.

    for (int i = ary.GetLowerBound(0); i <= ary.GetUpperBound(0); i++ )
    {}
    
    14.07.2015
  • Вы уверены, что вашего фрагмента кода достаточно? Просто посмотрите на другие ответы - все они содержат хорошее объяснение, в то время как ваш ответ низкого качества. 14.07.2015
  • Ответ краток, и объяснение может быть хорошим, но вопрос Is there an equivalent to High/Low in C#?. Они это предусмотрели. 15.07.2015
  • Иногда меньше значит лучше, а иногда немного проб и ошибок делает человека лучшим программистом. 16.07.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..