VB.NETコードをC#に移行するときに、forループの動作が異なるのはなぜですか?


87

プロジェクトをVisualBasicから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

ループが発生するたびに文字列の長さが変化する場合でもstringValue.Lengthforループ内の条件を使用して、Visual BasicがC#とどのように異なるかについての質問が解決されました。一方、C#では、stringValue.Lengthin the forloop条件を使用すると、ループが発生するたびに初期文字列値が変更されます。どうしてこれなの?


7
Microsoftは明らかにあなたの問題が何であるかを概説し...
Çöđěxěŕ

39
@Çöđěxěŕ:やめてください。コンテキストに関係なくタイトルからタグをロボットで削除することが役立つ場合は、Webサイトがそれを行います。
–ry-

11
@Çöđěxěŕここで
プーシキン2018年

35
@Çöđěxěŕ2つの投稿が互いに矛盾しているとは思いません。重要なのは、「このことについての質問-タグ」のように、タイトルに不自然にタグを付けないでください。ただし、タイトルがタグを含む完全な文である場合は、問題がない場合があります。「移行時にforループの動作が異なるのはなぜですか」は、あまりにも一般的なタイトルのように感じます。
プーシキン

26
@Çöđěxěŕ「VB.NETコードをC#に移行する」は、タイトルに役立つ情報を追加する完全なフレーズであることは明らかです。明瞭さを損なうような編集は行わないでください。うまくいけば、その概念は十分に常識であり、それをバックアップするためにメタ投稿は必要ありません。
jpmc26 2018年

回答:


115

C#では、ループ境界条件は反復ごとに評価されます。VB.NETでは、ループへの入り口でのみ評価されます。

だから、質問のC#バージョンでは、 stringValue、ループ内でのが変更されている、最終的なループ変数値が変更されます。

VB.NETでは、最終条件は包括的であるため、<=代わりにを使用します<、C#の。

C#の終了条件の評価には、変化はないものの計算にコストがかかる場合でも、ループの前に1回だけ計算する必要があるという当然の結果があります。


返信いただきありがとうございます。を使用<=すると、VBコードと同じ出力を繰り返し実行できることがわかりました。ただし、整数変数を宣言する必要があり、宣言する必要がなかった理由を知りたいと思っていVBます。同じ出力を表示するように質問を更新します。
slee423 2018年

@ slee423理由は私の答えの最初の文に示されています。の長さがstringValueループ内で変更されているため、最終的なループ変数値が変更されます。
アンドリューモートン

1
申し訳ありませんが、その回答に感謝します。そして、私のためにそれをより詳細に詳しく説明してくれてありがとう。
slee423 2018年

1
@ slee423確かにそれを明確にしているので、私はそれを答えに追加しました。
アンドリューモートン

22

ループが発生するたびに文字列の長さが変化しても、forループでstringValue.Length条件を使用すると、VBがC#とどのように異なるかについての質問が解決されます。

VB.NETのドキュメントによると:

counterwhileの値をループ内で変更すると、コードの読み取りとデバッグがより困難になる可能性があります。値を変更startendまたはstepループが最初に入力された際に決定された反復値に影響を与えません。

だから、の値 To 10 - stringValue.Lengthは1回評価され、ループが終了するまで再利用されます。

ただし、ステートメントについてc#を参照してください

場合はfor_condition現在または評価利回り場合ではないtrue、コントロールが埋め込まれた声明に転送されます。制御が埋め込みステートメントのエンドポイントに到達すると(おそらくcontinueステートメントの実行から)for_iterator、もしあれば、の式が順番に評価さfor_conditionれ、ステップでの評価から始めて、別の反復が実行されます。上記。

これは基本的に条件が ; i <= 10 - stringValueLength;が毎回再評価されるます。

したがって、ご覧のとおり、コードを複製する場合は、ループを開始する前にc#で最後のカウンターを宣言する必要があります。


11

例をより理解しやすくするために、両方のforループC# 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++;
}

違いは次のとおりです。

VB.NETはの最大値をキャッシュしますがiC#は毎回それを再計算します。


2
ループをwhileに変換する必要はありません
Panagiotis Kanavos 2018年

10
それは私がfor loops私の始めに理解するのを助けました、私は彼らがはるかに理解しやすいと思います。これが、while loops理解を助けるために、の例を「翻訳」した理由です。
Maxime Recuerda 2018年

7

のでforVBではとは異なるセマンティックですforC#(または他のCのような言語)のです

VBでは、 forステートメントは具体的に1つの値から別の値にカウンターをインクリメントしています。

C、C ++、C#などでは、forステートメントは単に3つの式を評価します。

  • 最初の式は通常、初期化です
  • 2番目の式は、各反復の開始時に評価され、終了条件が満たされているかどうかが判別されます。
  • 3番目の式は、各反復の最後に評価されます。これは通常、インクリメントです。

VBでは、あなたがしなければなりません、最終値に対してテストし、反復ごとに増分できる数値変数を指定ます

C、C ++、C#などでは、3つの式は最小限に制限されています。条件式は、true / false(またはC、C ++では整数のゼロ/非ゼロ)に評価される必要があります。初期化を実行する必要はまったくありません。任意の範囲の値に対して任意の型を反復するか、複雑な構造に対してポインターまたは参照を反復するか、何も反復しないことができます。

そのため、C#などでは、条件式を反復ごとに完全に評価する必要がありますが、VBでは、イテレータの最終値を最初に評価する必要があり、再度評価する必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.