Perché un ciclo for si comporta in modo diverso durante la migrazione del codice VB.NET in C #?


87

Sto migrando un progetto da Visual Basic a C # e ho dovuto modificare il modo forin cui viene dichiarato un ciclo utilizzato.

In VB.NET il forciclo è dichiarato di seguito:

Dim stringValue As String = "42"

For i As Integer = 1 To 10 - stringValue.Length
   stringValue = stringValue & " " & CStr(i)
   Console.WriteLine(stringValue)
Next

Quali uscite:

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

In C # il forciclo è dichiarato di seguito:

string stringValue = "42";

for (int i = 1; i <= 10 - stringValue.Length; i ++)
{
   stringValue = stringValue + " " + i.ToString();
   Console.WriteLine(stringValue);
}

E l'output:

42 1
42 1 2
42 1 2 3

Questo ovviamente non è corretto, quindi ho dovuto modificare leggermente il codice e ho incluso una variabile intera che avrebbe mantenuto la lunghezza della stringa.

Si prega di consultare il codice di seguito:

string stringValue = "42";
int stringValueLength = stringValue.Length;

for (int i = 1; i <= 10 - stringValueLength; i ++)
{
   stringValue = stringValue + " " + i.ToString();
   Console.WriteLine(stringValue);
}

E l'output:

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

Ora la mia domanda risolve il modo in cui Visual Basic differisce da C # in termini di Visual Basic utilizzando la stringValue.Lengthcondizione nel forciclo anche se ogni volta che si verifica il ciclo la lunghezza della stringa cambia. Mentre in C # se uso il stringValue.Lengthnella forcondizione del ciclo cambia il valore stringa iniziale ogni volta che si verifica il ciclo. Perchè è questo?


7
Microsoft delinea chiaramente qual è il tuo problema ...
Çöđěxěŕ

39
@ Çöđěxěŕ: Fermati, per favore. Se la rimozione robotica dei tag dal titolo senza riguardo al contesto fosse utile, il sito web lo farebbe.
Ry-

11
@ Çöđěxěŕ Puoi trovare alcune informazioni a riguardo qui
pushkin

35
@ Çöđěxěŕ Non credo che i due post si contraddicano a vicenda. Il punto è: non attaccare goffamente un tag nel titolo come "domanda su questa cosa - tag". Ma se il titolo è una frase completa che include il tag, a volte va bene. "Perché il ciclo for si comporta in modo diverso durante la migrazione" sembra un titolo troppo generico.
pushkin

26
@ Çöđěxěŕ "migrazione del codice VB.NET a C #" è chiaramente una frase completa che aggiunge informazioni utili al titolo. Non apportare modifiche che riducano la chiarezza. Si spera che questa nozione sia abbastanza sensata da non aver bisogno di un post Meta per sostenerla.
jpmc26

Risposte:


115

In C #, la condizione al contorno del ciclo viene valutata a ogni iterazione. In VB.NET, viene valutato solo all'ingresso nel ciclo.

Quindi, nella versione C # nella domanda, poiché la lunghezza di stringValueviene modificata nel ciclo, il valore della variabile del ciclo finale verrà modificato.

In VB.NET, la condizione finale è inclusiva, quindi la useresti <=invece che <in C #.

La valutazione della condizione finale in C # ha il corollario che, anche se non varia ma è costoso da calcolare, dovrebbe essere calcolata solo una volta prima del ciclo.


Grazie per la risposta. Ora mi rendo conto che l'utilizzo <=mi consente di iterare e avere lo stesso output del codice VB. Tuttavia, sono più interessato a sapere perché ho dovuto dichiarare la variabile intera e VBnon ho dovuto. Aggiornerò la mia domanda per mostrare lo stesso output.
slee423

@ slee423 Il motivo è fornito nella prima frase della mia risposta. Poiché la lunghezza di stringValueviene modificata nel ciclo, il valore della variabile del ciclo finale verrà modificato.
Andrew Morton

1
scuse, grazie per la risposta. E grazie per averlo elaborato in modo più dettagliato per me.
slee423

1
@ slee423 L'ho aggiunto nella risposta in quanto lo chiarisce.
Andrew Morton

22

Ora la mia domanda risolve il modo in cui VB differisce da C # in termini di VB utilizzando la condizione stringValue.Length nel ciclo for anche se ogni volta che si verifica il ciclo la lunghezza della stringa cambia.

Secondo la documentazione di VB.NET :

Se si modifica il valore di counterwhile all'interno di un ciclo, il codice potrebbe essere più difficile da leggere e da eseguire il debug. La modifica del valore di start, endo stepnon influisce sui valori di iterazione determinati quando è stato immesso per la prima volta il ciclo.

Quindi, il valore di To 10 - stringValue.Lengthviene valutato una volta e riutilizzato fino all'uscita dei cicli.

Tuttavia, guarda l' istruzione c # per

Se il for_conditionnon è presente o se la valutazione produce true, il controllo viene trasferito all'istruzione incorporata. Quando e se il controllo raggiunge il punto finale dell'istruzione incorporata (possibilmente dall'esecuzione di un'istruzione continue), le espressioni di for_iterator, se presenti, vengono valutate in sequenza, quindi viene eseguita un'altra iterazione, a partire dalla valutazione del for_conditionnel passaggio sopra.

Ciò significa sostanzialmente che la condizione ; i <= 10 - stringValueLength;viene valutata nuovamente ogni volta.

Quindi, come hai visto, se vuoi replicare il codice, devi dichiarare il contatore finale in c # prima di avviare il ciclo.


11

Per rendere l'esempio più comprensibile, convertirò entrambi i cicli for in C # cicli 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++;
}

C #

string stringValue = "42";

int i = 1;
while (i <= 10 - stringValue.Length)
{
    stringValue = stringValue + " " + stringValue.Length.ToString();
    Console.WriteLine(stringValue);
    i++;
}

La differenza è quindi:

VB.NET memorizza nella cache il valore massimo per i, ma C # lo ricalcola ogni volta.


2
Non è necessario convertire i loop in while
Panagiotis Kanavos

10
Mi ha aiutato a capire gli for loopsinizi, penso che siano molto più comprensibili. Questo è il motivo per cui ho "tradotto" gli esempi in while loops, per aiutare la comprensione.
Maxime Recuerda

7

Perché forin VB è una semantica diversa rispetto a forin C # (o qualsiasi altro linguaggio simile a C)

In VB, l' foristruzione incrementa specificamente un contatore da un valore a un altro.

In C, C ++, C # e così via, l' foristruzione valuta semplicemente tre espressioni:

  • La prima espressione è solitamente un'inizializzazione
  • La seconda espressione viene valutata all'inizio di ogni iterazione per determinare se la condizione terminale è stata soddisfatta
  • La terza espressione viene valutata alla fine di ogni iterazione, che di solito è un incrementatore.

In VB, è necessario fornire una variabile numerica che può essere verificata rispetto a un valore terminale e incrementata ad ogni iterazione

In C, C ++, C # e così via, le tre espressioni sono limitate al minimo; l'espressione condizionale deve restituire un valore vero / falso (o intero zero / diverso da zero in C, C ++). Non è necessario eseguire affatto un'inizializzazione, è possibile iterare qualsiasi tipo su qualsiasi intervallo di valori, iterare un puntatore o un riferimento su una struttura complessa o non iterare nulla.

Quindi, in C #, ecc., L'espressione della condizione deve essere valutata completamente a ogni iterazione, ma in VB, il valore terminale dell'iteratore deve essere valutato all'inizio e non è necessario valutarlo di nuovo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.