Я выполняю миграцию проекта с Visual Basic на С#, и мне пришлось изменить способ использования цикла for
.
В VB.NET цикл for
объявляется ниже:
Dim stringValue As String = "42"
For i As Integer = 1 To 10 - stringValue.Length
stringValue = stringValue & " " & CStr(i)
Console.WriteLine(stringValue)
Next
Какие результаты:
42 1
42 1 2
42 1 2 3
42 1 2 3 4
42 1 2 3 4 5
42 1 2 3 4 5 6
42 1 2 3 4 5 6 7
42 1 2 3 4 5 6 7 8
В С# цикл for
объявляется ниже:
string stringValue = "42";
for (int i = 1; i <= 10 - stringValue.Length; i ++)
{
stringValue = stringValue + " " + i.ToString();
Console.WriteLine(stringValue);
}
И выход:
42 1
42 1 2
42 1 2 3
Это, очевидно, неверно, поэтому мне пришлось немного изменить код и включить целочисленную переменную, которая будет содержать длину строки.
См. Следующий код:
string stringValue = "42";
int stringValueLength = stringValue.Length;
for (int i = 1; i <= 10 - stringValueLength; i ++)
{
stringValue = stringValue + " " + i.ToString();
Console.WriteLine(stringValue);
}
И выход:
42 1
42 1 2
42 1 2 3
42 1 2 3 4
42 1 2 3 4 5
42 1 2 3 4 5 6
42 1 2 3 4 5 6 7
42 1 2 3 4 5 6 7 8
Теперь мой вопрос решает, как Visual Basic отличается от С# в терминах Visual Basic, используя условие stringValue.Length
в цикле for
хотя каждый раз, когда цикл возникает, длина строки изменяется. В то время как в С#, если я использую stringValue.Length
в for
цикла условия он изменяет начальное значение каждый раз, когда строка, происходит цикл. Почему это?
В С# условие границы цикла вычисляется на каждой итерации. В VB.NET он оценивается только при входе в цикл.
Итак, в версии С# в вопросе, поскольку длина stringValue
изменяется в цикле, значение переменной конечного цикла будет изменено.
В VB.NET конечное условие включено, поэтому вы должны использовать <=
вместо <
в С#.
Оценка конечного условия в С# имеет следствие, что даже если оно не меняется, но оно дорого рассчитать, то оно должно быть рассчитано только один раз перед циклом.
<=
позволяет мне повторять и иметь тот же вывод, что и код VB. Тем не менее, мне больше интересно узнать, почему я должен был объявить целочисленную переменную, а в VB
нет. Я собираюсь обновить свой вопрос, чтобы показать тот же результат.
stringValue
изменяется в цикле, будет изменено окончательное значение переменной цикла.
Теперь мой вопрос решает, как VB отличается от С# в терминах VB, используя условие stringValue.Length в цикле for, хотя каждый раз, когда цикл возникает, длина строки изменяется.
Согласно документации VB.NET:
Если вы измените значение
counter
во время цикла, ваш код может быть труднее прочитать и отладить. Изменение значенияstart
,end
илиstep
не влияет на значения итерации, которые были определены при первом вводе цикла.
Таким образом, значение To 10 - stringValue.Length
оценивается один раз и повторно используется до тех пор, пока циклы не выйдут.
Однако посмотрите на оператор С# for
Если для параметра
for_condition
нет или если оценка дает значениеtrue
, управление передается встроенной инструкции. Когда и если элемент управления достигает конечной точки встроенного оператора (возможно, из выполнения оператора continue), выраженияfor_iterator
, если они есть, оцениваются последовательно, а затем выполняется другая итерация, начиная с оценкиfor_condition
в шаг выше.
Что в основном означает, что условие ; я <= 10 - stringValueLength;
; я <= 10 - stringValueLength;
оценивается снова каждый раз.
Итак, как вы видели, если вы хотите реплицировать код, вам нужно объявить окончательный счетчик в С# перед запуском цикла.
Чтобы сделать этот пример более понятным, я преобразую оба цикла в циклы С# while.
VB.NET
string stringValue = "42";
int min = 1;
int max = 10 - stringValue.Length;
int i = min;
while (i <= max)
{
stringValue = stringValue + " " + stringValue.Length.ToString();
Console.WriteLine(stringValue);
i++;
}
С#
string stringValue = "42";
int i = 1;
while (i <= 10 - stringValue.Length)
{
stringValue = stringValue + " " + stringValue.Length.ToString();
Console.WriteLine(stringValue);
i++;
}
Разница заключается в следующем:
VB.NET кэширует максимальное значение для
i
, но С# пересчитывает его каждый раз.
for loops
в начале, я думаю, они гораздо более понятны. Вот почему я «перевел» примеры в while loops
, чтобы помочь пониманию.
Поскольку for
в VB является другой семантический, чем for
в С# (или любого другого С-подобном языке)
В VB оператор for
специально увеличивает счетчик от одного значения к другому.
В C, C++, С# и т.д. Оператор for
просто оценивает три выражения:
В VB вы должны указать числовую переменную, которая может быть протестирована против значения терминала и увеличена на каждой итерации
В C, C++, С# и т.д. Три выражения минимально ограничены; условное выражение должно оцениваться как true/false (или целое число нуль/ненулевое значение в C, C++). Вам вообще не нужно выполнять инициализацию, вы можете перебирать любой тип по любому диапазону значений, перебирать указатель или ссылку на сложную структуру или вообще не перебирать что-либо.
Таким образом, в С# и т.д. Выражение условия должно быть полностью оценено на каждой итерации, но в VB конечное значение итератора должно быть оценено в начале и не нужно снова оценивать.