- PR -

VBでのWhile系のループの書き方

投稿者投稿内容
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2007-02-01 21:53
こんばんは。
ここの会議室の過去ログしか検索してないので、
他所では既に存在する話題かもしれませんが…

C#で以下のようなコードがあったとします。

コード:

using (StreamReader reader = new StreamReader(略)
using (StreamWriter writer = new StreamWriter(略)
{
    string s;
    while ((s = reader.ReadLine()) != null)
    {
        if(s.Trim().Length > 0) writer.WriteLine(s);
    }
}


これを同じ動作をするようにVB2005で書き換えた場合、
皆さんならどのように書きますか?
書き方はいろいろあると思うんですけど、
どんな書き方が一番スマートかって考えると、
いまいちしっくりくるのが見当たらなくて…(^^;
hei
ベテラン
会議室デビュー日: 2006/09/07
投稿数: 78
投稿日時: 2007-02-01 22:44
こんばんは。
ほぼ同じですが、

Using reader As New StreamReader("c:\hoge.txt"), writer As New StreamWriter("c:\hage.txt")
While Not reader.EndOfStream
Dim s As String = reader.ReadLine
If s.Trim.Length > 0 Then writer.WriteLine(s)
End While
End Using
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-02 11:34
引用:

ぼのぼのさんの書き込み (2007-02-01 21:53) より:

これを同じ動作をするようにVB2005で書き換えた場合、皆さんならどのように書きますか?書き方はいろいろあると思うんですけど、どんな書き方が一番スマートかって考えると、いまいちしっくりくるのが見当たらなくて…(^^;


この話題は、VB では '同じように記述することができない' ことに端を発していますよね。
VB では、C# のように '=' 演算子と '==' 演算子の区別がないため、式の結果しか即座に評価することができません。
(代入結果を即座に評価できないの意)

同じ動作をするようにとなると、hei さんの記述したとおりになるでしょう。
1.1 だと EndOfStream プロパティがないので、Peek メソッドを使用します。

どうしても、ReadLine メソッドの戻り値で判定しようとすると...

コード:

    Using reader As New System.IO.StreamReader(略), writer As New System.IO.StreamWriter(略) 
        Dim s As String = reader.ReadLine()

        While (Not s Is Nothing)
            If s.Trim().Length > 0 Then
                writer.WriteLine(s)
            End If

            s = reader.ReadLine()
        End While
    End Using


変数 's' の位置が気に入らないですね。
やはり、EndOfStream プロパティか Peek メソッドを使うのがしっくりきます。

コード:

    Using reader As New System.IO.StreamReader(略), writer As New System.IO.StreamWriter(略) 
        While (Not reader.EndOfStream)
            Dim s As String = reader.ReadLine()

            If s.Trim().Length > 0 Then
                writer.WriteLine(s)
            End If
        End While
    End Using


変数 's' の位置がしっくりきて良いですね。

# 個人的には 's' の位置どうこうより、Using の使い方が一寸嫌いだったり...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-02-02 11:44
引用:

heiさんの書き込み (2007-02-01 22:44) より:

Using reader As New StreamReader("c:hoge.txt"), writer As New StreamWriter("c:hage.txt")


この時ってどう展開されるんだろう。
reader の dispose で例外が発生した場合も writer の dispose は保障されるのかな
_________________
かるあ のメモスニペット
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2007-02-02 13:02
#本題からちょいとそれますが・・・

引用:

じゃんぬねっとさんの書き込み (2007-02-02 11:34) より:
この話題は、VB では '同じように記述することができない' ことに端を発していますよね。
VB では、C# のように '=' 演算子と '==' 演算子の区別がないため、式の結果しか即座に評価することができません。
(代入結果を即座に評価できないの意)



正確にはVBでは代入は文であり、C#では代入は式であるという言語仕様の違いから来るものですね。
もっとも代入を式として扱う言語仕様にするには、代入と等式とを区別できる
字句文法にしておく必要がありますので、じゃんぬさんのおっしゃることも
理由の一つではありますけど。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2007-02-02 22:19
引用:

じゃんぬねっとさんの書き込み (2007-02-02 11:34) より:

この話題は、VB では '同じように記述することができない' ことに端を発していますよね。
VB では、C# のように '=' 演算子と '==' 演算子の区別がないため、式の結果しか即座に評価することができません。
(代入結果を即座に評価できないの意)


そう、話題にしたかったのはそこです。
だからSreamReaderは例として挙げただけで、終端に達したことを戻り値で返すメソッドを使ってループさせる時一般の話がしたかったのです。

とはいえEndOfStreamプロパティの存在は今まで気づいてなかったので、ちゃっかり勉強になりましたが(_ _*

新たに例を挙げるのもめんどくさいので

引用:

どうしても、ReadLine メソッドの戻り値で判定しようとすると...


という前提で話をすすめてしまうと、

コード:

Dim s As String = reader.ReadLine()
While (Not s Is Nothing)
    If s.Trim().Length > 0 Then writer.WriteLine(s)
    s = reader.ReadLine()
End While


VBの場合やっぱりこの書き方が一番一般的なのでしょうか?
ただ、ReadLine()を2ヶ所に書かなきゃいけないのと、sのスコープがループ内にならないのとありますよね。
でも、1回目のReadLineでいきなりNothingになることを考えると、後判定にはできないので、解決策としては

コード:

Do
    Dim s As String = reader.ReadLine()
    If s Is Nothing Then Exit Do
    If s.Trim().Length > 0 Then writer.WriteLine(s)
Loop


となります。これだとsのスコープもループ内になるしReadLineを書くのも1ヶ所だけ。
個人的にこの書き方結構好きなんですけど、世間一般には条件句のないDo〜Loopを嫌う人が結構いるんですよね。

で、そこらへんも含めてこの会議室に出入りしてる方々はどうなんだろうと思ったわけです。

以下は余談ですが、

引用:

変数 's' の位置が気に入らないですね。


この理由がループ内でしか使わない変数のスコープがループ内でないことだとしたら、最初に挙げたC#のコードも一緒ですよね。
C#ならこの書き方が一番一般的かな〜と思ったんですが、そうでもないんでしょうか?
#Usingのとこじゃなくて、あくまでループのとこですよ

引用:

# 個人的には 's' の位置どうこうより、Using の使い方が一寸嫌いだったり...


ネストを浅くするために安直に使ってみたんですが、なんか問題ありますかね?
かるあさんの例みたいに同じモノを指定されることはさすがに考えてなかったんですが…
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-02-03 00:22
コード:

using (StreamReader reader = new StreamReader(略)
using (StreamWriter writer = new StreamWriter(略)
{
string s;



これって

コード:

using (StreamReader reader = new StreamReader(略)
using (StreamWriter writer = new StreamWriter(略)
{
string s = null;



みたいに初期化しないと警告出ませんでしたっけ?
(直下で代入してるから出ないのかな?)

この s の初期化が無意味でイヤなので、個人的には

コード:

for (string s = reader.ReadLine(); s != null; s = reader.ReadLine())
{



と書きます。


_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/

[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-02-03 00:22 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-02-03 11:23
引用:

よねKENさんの書き込み (2007-02-02 13:02) より:

正確にはVBでは代入は文であり、C#では代入は式であるという言語仕様の違いから来るものですね。


フォローさせてしまって申し訳ないです。
そういうことを言いたかったのですが、うまい説明が思い浮かびませんでした。
'=' 演算子と '==' 演算子のような区別がなくても良い理由の根本はそっちですね。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)