เหตุใด for loop จึงทำงานแตกต่างกันเมื่อย้ายรหัส VB.NET ไปที่ C #


87

ฉันอยู่ระหว่างการย้ายโปรเจ็กต์จาก Visual Basic เป็น C # และฉันต้องเปลี่ยนวิธีการประกาศ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

ใน C # 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 แตกต่างจาก C # อย่างไรในแง่ของ Visual Basic โดยใช้stringValue.Lengthเงื่อนไขในforลูปแม้ว่าทุกครั้งที่การวนซ้ำเกิดขึ้นความยาวของสตริงจะเปลี่ยนไป ในขณะที่ C # ถ้าฉันใช้stringValue.Lengthในforเงื่อนไขลูปมันจะเปลี่ยนค่าสตริงเริ่มต้นทุกครั้งที่ลูปเกิดขึ้น ทำไมถึงเป็นแบบนี้?


8
Microsoftสรุปอย่างชัดเจนว่าปัญหาของคุณคืออะไร ...
Codexer

39
@ Çöđěxěŕ: หยุดได้โปรด หากการนำแท็กออกจากหัวเรื่องโดยอัตโนมัติโดยไม่คำนึงถึงบริบทเป็นประโยชน์เว็บไซต์ก็จะดำเนินการดังกล่าว
Ry-

11
@ Çöđěxěŕคุณสามารถค้นหาข้อมูลบางอย่างได้ที่นี่
pushkin

35
@ Çöđěxěŕฉันไม่คิดว่าทั้งสองโพสต์ขัดแย้งกัน ประเด็นคืออย่าติดแท็กในชื่อเรื่องอย่างเชื่องช้าเช่น "คำถามเกี่ยวกับสิ่งนี้ - แท็ก" แต่ถ้าชื่อเป็นประโยคสมบูรณ์ที่มีแท็กบางครั้งก็ใช้ได้ "เหตุใดสำหรับการวนซ้ำจึงทำงานแตกต่างกันเมื่อย้ายข้อมูล" ให้ความรู้สึกเหมือนชื่อเรื่องทั่วไปเกินไป
pushkin

26
@ Çöđěxěŕ "การย้ายรหัส VB.NET ไปที่ C #" เป็นวลีที่ชัดเจนซึ่งเพิ่มข้อมูลที่เป็นประโยชน์ให้กับชื่อ อย่าทำการแก้ไขที่ทำให้ความชัดเจนลดลง หวังว่าแนวคิดดังกล่าวจะเป็นสามัญสำนึกเพียงพอที่เราไม่จำเป็นต้องมีโพสต์ Meta เพื่อสำรองข้อมูล
jpmc26

คำตอบ:


115

ใน C # เงื่อนไขขอบเขตการวนซ้ำจะถูกประเมินในการวนซ้ำแต่ละครั้ง ใน VB.NET จะได้รับการประเมินเมื่อเข้าสู่ลูปเท่านั้น

ดังนั้นในเวอร์ชัน C # ในคำถามเนื่องจากความยาวของstringValueการเปลี่ยนแปลงในลูปค่าตัวแปรลูปสุดท้ายจะเปลี่ยนไป

ใน VB.NET เงื่อนไขสุดท้ายจะรวมอยู่ด้วยดังนั้นคุณจะใช้<=แทน<ใน C #

การประเมินเงื่อนไขสิ้นสุดใน C # มีข้อสรุปที่แม้ว่าจะไม่แตกต่างกัน แต่มีราคาแพงในการคำนวณดังนั้นควรคำนวณเพียงครั้งเดียวก่อนลูป


ขอบคุณสำหรับการตอบกลับ. ตอนนี้ฉันรู้แล้วว่าการใช้<=ช่วยให้ฉันทำซ้ำและมีผลลัพธ์เหมือนกับรหัส VB อย่างไรก็ตามฉันสนใจที่จะรู้มากขึ้นว่าทำไมฉันต้องประกาศตัวแปรจำนวนเต็มและVBฉันไม่จำเป็นต้องทำ ฉันจะอัปเดตคำถามของฉันเพื่อแสดงผลลัพธ์เดียวกัน
slee423

@ slee423 เหตุผลอยู่ในประโยคแรกของคำตอบของฉัน เนื่องจากความยาวของstringValueการเปลี่ยนแปลงในลูปค่าตัวแปรลูปสุดท้ายจะเปลี่ยนไป
Andrew Morton

1
ขอโทษขอบคุณสำหรับคำตอบนั้น และขอขอบคุณที่อธิบายรายละเอียดเพิ่มเติมให้ฉัน
slee423

1
@ slee423 ฉันเพิ่มสิ่งนั้นลงในคำตอบเพราะมันชี้แจงได้อย่างแท้จริง
Andrew Morton

22

ตอนนี้คำถามของฉันได้ไขข้อข้องใจว่า VB แตกต่างกับ C # อย่างไรในแง่ของ VB โดยใช้ stringValue เงื่อนไขความยาวใน for loop แม้ว่าทุกครั้งที่ลูปเกิดขึ้นความยาวของสตริงจะเปลี่ยนไป

ตามเอกสารVB.NET :

หากคุณเปลี่ยนค่าของcounterwhile อยู่ในลูปโค้ดของคุณอาจอ่านและแก้ไขข้อบกพร่องได้ยากขึ้น การเปลี่ยนค่าของstart, endหรือstepไม่ได้ส่งผลกระทบต่อค่าซ้ำที่ถูกกำหนดขึ้นเมื่อวงถูกป้อนแรก

ดังนั้นค่าของTo 10 - stringValue.Lengthจะถูกประเมินครั้งเดียวและใช้ซ้ำจนกว่าลูปจะออก

อย่างไรก็ตามดูที่c # สำหรับคำสั่ง

ถ้าfor_conditionไม่มีอยู่หรือถ้าการประเมินให้ผลtrueการควบคุมจะถูกโอนไปยังคำสั่งฝังตัว เมื่อและถ้าการควบคุมไปถึงจุดสิ้นสุดของคำสั่งฝังตัว (อาจมาจากการดำเนินการของคำสั่งดำเนินการต่อ) นิพจน์ของfor_iteratorถ้ามีจะได้รับการประเมินตามลำดับจากนั้นจะทำการวนซ้ำอีกครั้งโดยเริ่มจากการประเมินfor_conditionในขั้นตอน ข้างบน.

ซึ่งโดยพื้นฐานแล้วหมายความว่าเงื่อนไข; i <= 10 - stringValueLength;จะได้รับการประเมินอีกครั้งในแต่ละครั้ง

อย่างที่คุณเห็นถ้าคุณต้องการจำลองโค้ดคุณต้องประกาศตัวนับสุดท้ายใน c # ก่อนเริ่มลูป


11

เพื่อที่จะทำให้ตัวอย่างที่เข้าใจมากขึ้นผมจะแปลงสำหรับลูปลงในC #ในขณะที่ลูป

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แต่C #จะคำนวณใหม่ทุกครั้ง


2
คุณไม่จำเป็นต้องแปลงลูปเป็น while
Panagiotis Kanavos

10
มันช่วยให้ฉันเข้าใจจุดfor loopsเริ่มต้นของฉันฉันคิดว่าพวกเขาเข้าใจมากขึ้น นี่คือเหตุผลที่ฉัน 'แปล' ตัวอย่างในwhile loopsเพื่อช่วยให้เข้าใจ
Maxime Recuerda

7

เนื่องจากforใน VB เป็นความหมายที่แตกต่างจากforใน C # (หรือภาษาอื่นที่คล้าย C)

ใน VB forคำสั่งจะเพิ่มตัวนับจากค่าหนึ่งไปยังอีกค่าหนึ่งโดยเฉพาะ

ใน C, C ++, C # ฯลฯforคำสั่งจะประเมินนิพจน์สามนิพจน์:

  • นิพจน์แรกเป็นค่าเริ่มต้นตามปกติ
  • นิพจน์ที่สองได้รับการประเมินเมื่อเริ่มต้นการทำซ้ำแต่ละครั้งเพื่อพิจารณาว่าตรงตามเงื่อนไขเทอร์มินัลหรือไม่
  • นิพจน์ที่สามจะได้รับการประเมินเมื่อสิ้นสุดการทำซ้ำแต่ละครั้งซึ่งโดยปกติจะเป็นตัวเพิ่ม

ใน VB คุณต้องใส่ตัวแปรตัวเลขซึ่งสามารถทดสอบกับค่าเทอร์มินัลและเพิ่มขึ้นในการวนซ้ำแต่ละครั้ง

ใน C, C ++, C # ฯลฯ ทั้งสามนิพจน์จะถูก จำกัด ให้น้อยที่สุด นิพจน์เงื่อนไขต้องประเมินเป็นจริง / เท็จ (หรือจำนวนเต็มศูนย์ / ไม่ใช่ศูนย์ใน C, C ++) คุณไม่จำเป็นต้องทำการกำหนดค่าเริ่มต้นเลยคุณสามารถวนซ้ำประเภทใดก็ได้ในช่วงของค่าใด ๆ ย้ำตัวชี้หรือการอ้างอิงบนโครงสร้างที่ซับซ้อนหรือไม่ทำซ้ำอะไรเลย

ดังนั้นใน C # ฯลฯ นิพจน์เงื่อนไขต้องได้รับการประเมินอย่างสมบูรณ์ในการทำซ้ำแต่ละครั้ง แต่ใน VB ค่าเทอร์มินัลของตัววนซ้ำจะต้องได้รับการประเมินในตอนเริ่มต้นและไม่จำเป็นต้องได้รับการประเมินอีกครั้ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.