Mengapa perulangan for berperilaku berbeda saat memigrasi kode VB.NET ke C #?

87

Saya sedang dalam proses migrasi proyek dari Visual Basic ke C # dan saya harus mengubah cara a for deklarasi loop yang digunakan.

Di VB.NET, forloop dideklarasikan di bawah ini:

Dim stringValue As String = "42"

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

Output mana:

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

Di C # forloop dideklarasikan di bawah ini:

string stringValue = "42";

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

Dan hasilnya:

42 1
42 1 2
42 1 2 3

Ini jelas tidak benar jadi saya harus mengubah kode sedikit dan memasukkan variabel integer yang akan menahan panjang string.

Silakan lihat kode di bawah ini:

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

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

Dan hasilnya:

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

Sekarang pertanyaan saya menyelesaikan sekitar bagaimana Visual Basic berbeda dengan C # dalam hal Visual Basic menggunakan stringValue.Lengthkondisi dalam forloop meskipun setiap kali loop terjadi panjang string berubah. Sedangkan di C # jika saya menggunakan kondisi stringValue.Lengthdalam forloop itu mengubah nilai string awal setiap kali loop terjadi. Kenapa ini?

lengan423
sumber
8
Microsoft dengan jelas menguraikan apa masalah Anda ...
Codexer
39
@ Çöđěxěŕ: Tolong, berhenti. Jika menghapus tag secara robotik dari judul tanpa memperhatikan konteks sangat membantu, situs web akan melakukannya.
Ry-
11
@ Çöđěxěŕ Anda dapat menemukan beberapa info tentang itu di sini
pushkin
35
@ Çöđěxěŕ Saya tidak berpikir bahwa kedua kiriman tersebut saling bertentangan. Intinya adalah: jangan dengan canggung menempelkan tag di judul seperti "pertanyaan tentang hal ini - tag". Tetapi jika judul adalah kalimat lengkap yang menyertakan tag, terkadang tidak masalah. "Mengapa for loop berperilaku berbeda saat bermigrasi" terasa seperti judul yang terlalu umum.
pushkin
26
@ Çöđěxěŕ "memigrasikan kode VB.NET ke C #" jelas merupakan frasa lengkap yang menambahkan informasi berguna ke judul. Jangan melakukan pengeditan yang mengurangi kejelasan. Mudah-mudahan, gagasan itu cukup masuk akal sehingga kita tidak memerlukan postingan Meta untuk mendukungnya.
jpmc26

Jawaban:

115

Dalam C #, kondisi batas loop dievaluasi pada setiap iterasi. Di VB.NET, ini hanya dievaluasi saat masuk ke loop.

Jadi, dalam versi C # di pertanyaan, karena panjangnya stringValue diubah dalam perulangan, nilai variabel perulangan terakhir akan berubah.

Dalam VB.NET, kondisi akhir inklusif, sehingga Anda akan menggunakan <=bukannya< di C #.

Evaluasi kondisi akhir di C # memiliki konsekuensi bahwa meskipun tidak bervariasi tetapi mahal untuk dihitung, harus dihitung sekali sebelum loop.

Andrew Morton
sumber
Terima kasih balasannya. Sekarang saya menyadari bahwa menggunakan <=memungkinkan saya untuk mengulang dan memiliki keluaran yang sama dengan kode VB. Namun, saya lebih tertarik untuk mengetahui mengapa saya harus mendeklarasikan variabel integer dan VBsaya tidak perlu melakukannya. Saya akan memperbarui pertanyaan saya untuk menunjukkan hasil yang sama.
slee423
@ slee423 Alasannya diberikan di kalimat pertama jawaban saya. Karena panjang dari stringValuesedang diubah dalam loop, nilai variabel loop terakhir akan berubah.
Andrew Morton
1
maaf, terima kasih atas jawaban itu. Dan terima kasih telah menjelaskannya lebih detail untuk saya.
slee423
1
@ slee423 Saya menambahkannya ke dalam jawaban karena memang menjelaskannya.
Andrew Morton
22

Sekarang pertanyaan saya menyelesaikan sekitar bagaimana VB berbeda dengan C # dalam hal VB menggunakan kondisi stringValue.Length di loop for meskipun setiap kali terjadi loop, panjang string berubah.

Menurut dokumentasi VB.NET :

Jika Anda mengubah nilai counterwhile di dalam loop, kode Anda mungkin lebih sulit untuk dibaca dan di-debug. Mengubah nilai start, endatau steptidak mempengaruhi nilai iterasi yang ditentukan ketika lingkaran pertama kali masuk.

Jadi, nilai dari To 10 - stringValue.Lengthdievaluasi sekali dan digunakan kembali hingga loop keluar.

Namun, lihat c # untuk pernyataan

Jika for_conditiontidak ada atau jika evaluasi menghasilkan true, kontrol dialihkan ke pernyataan tertanam. Ketika dan jika kontrol mencapai titik akhir dari pernyataan yang disematkan (mungkin dari eksekusi pernyataan lanjutan), ekspresi dari for_iterator, jika ada, dievaluasi secara berurutan, dan kemudian iterasi lain dilakukan, dimulai dengan evaluasi for_conditionpada langkah atas.

Yang pada dasarnya berarti bahwa kondisi ; i <= 10 - stringValueLength;tersebut dievaluasi kembali setiap kali.

Jadi, seperti yang Anda lihat, jika Anda ingin mereplikasi kode, Anda perlu mendeklarasikan penghitung terakhir di c # sebelum memulai loop.

Camilo Terevinto
sumber
11

Untuk membuat contoh lebih mudah dimengerti, saya akan mengonversi kedua for loop menjadi C # while loop .

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++;
}

Perbedaannya kemudian:

VB.NET menyimpan nilai maksimum untuk i, tetapi C # menghitung ulang setiap saat.

Maxime Recuerda
sumber
2
Anda tidak perlu mengonversi loop menjadi while
Panagiotis Kanavos
10
Ini membantu saya untuk memahami awal for loopssaya, saya pikir mereka jauh lebih bisa dimengerti. Inilah mengapa saya 'menerjemahkan' contoh while loops, untuk membantu pemahaman.
Maxime Recuerda
7

Karena fordi VB adalah semantik yang berbeda dari fordi C # (atau bahasa C-like lainnya)

Dalam VB, forpernyataan secara khusus menaikkan penghitung dari satu nilai ke nilai lainnya.

Di C, C ++, C #, dll., forPernyataan itu hanya mengevaluasi tiga ekspresi:

  • Ekspresi pertama biasanya merupakan inisialisasi
  • Ekspresi kedua dievaluasi pada awal setiap iterasi untuk menentukan apakah kondisi terminal telah terpenuhi
  • Ekspresi ketiga dievaluasi pada akhir setiap iterasi, yang biasanya merupakan incrementer.

Di VB, Anda harus menyediakan variabel numerik yang dapat diuji terhadap nilai terminal dan bertambah pada setiap iterasi

Dalam C, C ++, C #, dll., Ketiga ekspresi tersebut dibatasi secara minimal; ekspresi kondisional harus bernilai true / false (atau integer nol / bukan nol di C, C ++). Anda tidak perlu melakukan inisialisasi sama sekali, Anda dapat mengulang tipe apa pun pada rentang nilai apa pun, mengulang penunjuk atau referensi pada struktur yang kompleks, atau tidak mengulangi apa pun sama sekali.

Jadi, di C #, dll., Ekspresi kondisi harus sepenuhnya dievaluasi pada setiap iterasi, tetapi di VB, nilai terminal dari iterator harus dievaluasi di awal, dan tidak perlu dievaluasi lagi.

C Robinson
sumber