- PR -

VBのWithってC#でどう書くんですか?

投稿者投稿内容
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-18 14:10
引用:

unibonさんの書き込み (2006-02-18 12:44) より:

ただ、こういう使い捨ての一時変数なのかそれとも、後でまた使うことがある変数なのかが分からない


そうですね、バグの温床にもなるので構文レベルでサポートするのが 1 番でしょう。
それこそが With ステートメントなわけですので、代わりになる機構がないように思えます。

引用:

そういう目印を付けられるような言語仕様になっていたほうが良いなあと


この目印のために、With ステートメントは存在し、インデントが存在するんですよね。
インデントに関しては、メソッド内から見たルート位置からのインデントであれば、
そこまで可読性が落ちるわけでもなさそうです。

明らかに可読性が落ちると感じるのは、ルート位置からのインデントでない場合と、
With ステートメント内で別のインデントが発生する場合だと思います。
(そういう書き方 "も" できること、そういう書き方をする人が多い (orz) ことは問題ですがw)

引用:

でもこれだと記号に変わっただけだなあ。


今回の例だと、クラス直下のメンバなので、別の参照に取る利点はない... というのはおいといて、
この書き方だと、素直にそのまま書いたのと大差がないような気がします。

With と比べた場合に、その大差がない理由のひとつとして、
変数が変わった場合の置換ミス防止などがあげられます。

別の変数に代わった場合に、全部置換することになりますので、
この書き方であっても With ステートメントの保守的な意味合いをひとつ逃しているんですよね。

1 箇所のみ置換すれば良いとか、そういう次元だったりするんですが、
With ステートメントの利点ってそういう限定的なことでしか思いつかないんですよね。
あとはスコープの範囲がありますが、この点は C# には機構がありますしw

コンパイラが賢くなった今、この程度であれば素直にそのまま書いた方が良いでしょうね。

# ああ、相変わらずうまく書けてない。orz

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-18 14:43
引用:

R・田中一郎さんの書き込み (2006-02-18 14:03) より:

うーむ、僕が With を多用していた頃によく思ったのは、今の using のような
ことが一定のスコープ内でできればいいなーということでした。


あ、最初に私が書いたトリッキーなアレの話はコレなんですよねw
C# には { } で、限定的なスコープにしてしまえる機構があるわけですが、
VB で、代わりとなりそうなのが、こういう With ステートメントの使い方ですよね。

コード:

    Private Sub BindingComboBox()
        Dim wankumaList As New System.Collections.ArrayList()

        With Me
            Dim item As New WankumaItem(1, "中博俊")
            wankumaList.Add(item)
        End With

        With Me
            Dim item As New WankumaItem(2, "じゃんぬ")
            wankumaList.Add(item)
        End With

        With Me
            Dim item As New WankumaItem(3, "Jitta")
            wankumaList.Add(item)
        End With
            :
            :
        Me.ComboBox.DataSource    = wankumaList
        Me.ComboBox.ValueMember   = "MemberID"
        Me.ComboBox.DisplayMember = "MemberName")
    End Sub


あまり良い例ではないかもしれませんが、ComboBox へのバインドが例になっています。
回避方法はあるので、こんな書き方する必要はないんですが、
回避方法が面倒という場合には、たまに使ったりしますね! (w

今回のようにする利点として、スコープの有効範囲が見やすいこと、
他では使っていないことを明示化できることがあげられます。
このブロック外ではアクセスできないのですから、安全であることが保証できます。

「"同名の" 安易な変数名」が使えることも利点でしょう。
通常、変数名は厳密な名前を付けるべきですが、
あまり重要でない変数には、安易な名前をつけた方が良い場合があります。

今回の例で考えると、"item" に対して別々の名前をつけた場合、
 「他の変数名が際立たなくなる」もしくは、
 「大した意味はないのに、意味があるかのように見えてしまう」という副作用を生みます。
これは、For で配列を取り出す場合の "ループ変数" に厳密な名前を付けた時の副作用と同じですね。

そういった理由で、「同名の安易な変数名」と「限定されたスコープの変数」を使いたくなることはありますね。

# すいません、うまく説明できていません。(;_ _)

でもなぁ、これだったら、If True Then と書いた方が良いかもしれませんね。

コード:

    If True Then
        Dim item As New WankumaItem(1, "中博俊")
        wankumaList.Add(item)
    End If


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-02-18 14:49
同じようなことを考える人はいるようで、、、
http://www.gotdotnet.com/team/ja/team/csharp/learn/columns/ask.aspx
http://cspc.jp/~eclipse/archives/000699.html
http://www.hey-to.net/ML-archive/vcppML/2000/msg07130.html

with を使わないようにリファクタリングされるそうです
http://www.ailight.jp/blog/papanvb/archive/2005/09/12/9707.aspx
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-02-18 15:12
引用:

じゃんぬねっとさんの書き込み (2006-02-18 14:43) より:

あ、最初に私が書いたトリッキーなアレの話はコレなんですよねw
C# には { } で、限定的なスコープにしてしまえる機構があるわけですが、
VB で、代わりとなりそうなのが、こういう With ステートメントの使い方ですよね。



これは目から鱗ものですね。
しかし僕は VB6 使いだったので、ブロック内のみ有効スコープな変数を使うことさ
えできませんでしたが。
{} は Perl で多用していました。

引用:

じゃんぬねっとさんの書き込み (2006-02-18 14:43) より:

でもなぁ、これだったら、If True Then と書いた方が良いかもしれませんね。

コード:


If True Then
Dim item As New WankumaItem(1, "中博俊")
wankumaList.Add(item)
End If






僕が VB6 の頃によく使っていた手も有効かも知れません。

コード:


VB6 のコードです。

private sub ファイルを読んでいろいろ処理する()
dim f as ファイル処理クラス
set f = new ファイル処理;
if (not f.開く()) then
exit sub
end if
do
if (not f.レコードを取り出す()) then
exit do
end if
if (not f.いろいろな処理をする()) then
exit do
end if
loop while false
call f.ファイルを閉じる
set f = nothing
end sub


後始末が必要な場合は、大体この書き方でした。

引用:

Jittaさんの書き込み (2006-02-18 14:49) より:
同じようなことを考える人はいるようで、、、
http://www.gotdotnet.com/team/ja/team/csharp/learn/columns/ask.aspx
http://cspc.jp/~eclipse/archives/000699.html
http://www.hey-to.net/ML-archive/vcppML/2000/msg07130.html

with を使わないようにリファクタリングされるそうです
http://www.ailight.jp/blog/papanvb/archive/2005/09/12/9707.aspx




僕があれだけキーワードを駆使して調べられなかったのに、何気にたくさんの情報
収集ができてしまうのですね。
僕は調べるのが下手なんだろうか orz

[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-02-18 15:21 ]

[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-02-18 15:22 ]
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2006-02-18 15:38
R・田中一郎さん、こんにちは。

引用:

しかし、With の何が嫌って .Width のように . から始まるところです。

なので、


ドットで始まらないと、メンバなのかどうかが判別できないような気が…。

#ドットを打つと同時にインテリセンスが働いてくれるので、入力が楽だったりしますね。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-18 15:52
引用:

Jittaさんの書き込み (2006-02-18 14:49) より:

http://www.gotdotnet.com/team/ja/team/csharp/learn/columns/ask.aspx


これに関して言えば、
 「with ブロック内は with で指定したオブジェクト以外に関する記述はできない」
 「with に限らず他のブロックを入れ子にすることはできない」
 「メソッドの呼び出しはできない」
 「...というより、プロパティなどの初期化にしか使えない」
という仕様にすれば少しは解決しそうなんですけどね。

可読性が損なわれる、の多くは VB プログラマ (ただし、困った人のみ) に多い、
複雑な With ステートメントの書き方を危惧してのことでしょうから。
たとえば以下のような使い方は、本人以外は読みにくいと感じるでしょう。

コード:

    With Hoge.Foo.Piyo
        .Property1 = 1
        .Property2 = 2

        ''' (1)
        BetsuNoClass.KankeiNaiMethod()

        ''' (2)
        If BetsuNoClass.IsPrity() Then
            .Prity = True
        End If

        ''' (3)
        For i As Integer = 0 To .Count - 1
            .Item(i).Name = "Name" & i.ToString()
        Next i
    End With


(1) にあるように、With で指定したオブジェクトと関連のないメソッドの呼び出しとか。
(2) にあるように、別のステートメント ブロックが入れ子で入ってしまったりとか。
(3) にあるように、For に .Count なんてあったりとか。
(For ステートメントは最初の 1 行で "すべて" が把握できる機構になっているのに、それを壊している)

こういう使い方をある程度防止できれば、まだマシでしょうね。

とはいえ、私も反対寄りの意見になると思います。
深いネストでの使用については、コンパイラで叱り付けるのは難しいでしょうからね。

個人的な意見ばかりになってしまいましたが、たとえ、VB6 であっても、
With ステートメントは、プロパティの初期化くらいにして欲しいものです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2006-02-18 15:59
引用:

じゃんぬねっとさんの書き込み (2006-02-18 15:52) より:

 「...というより、プロパティなどの初期化にしか使えない」


そう言えば C# 3.0 のインスタンスイニシャライザがまさにそれですね。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-18 16:20
引用:

Hongliangさんの書き込み (2006-02-18 15:59) より:

そう言えば C# 3.0 のインスタンスイニシャライザがまさにそれですね。


以下の初期化記法のことですね?

# イニシャライザと聞いて、静的コンストラクタを真っ先に思い浮かべ、
# でも、インスタンスって書いてあるし、うーん。と、しばらく考えこんでましたw

コード:

    Rectangle rect = new Rectangle {X = 32, Y = 64, Width = 128, Height = 256};


ブロックみたいに書くならば、

コード:

    Rectangle rect = new Rectangle {
        X      = 32,
        Y      = 64,
        Width  = 128,
        Height = 256 
    };


多分、こんな感じかな。

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

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