• ベストアンサー

For ~ Next の中での Dim宣言について

四角形を下方向にずらしながら繰り返し描きたい場合、 以下のソースのようにFor ~ Next の中での Dim宣言を 行うのは一般的でしょうか。 他にスマートな記述があれば教えてください。 よろしくお願いします。 --------------------------------------- '四角形を下方向にずらしながら描画 For i = 0 To 10   Dim rect As New Rectangle(x, y* i , w, h)   g.DrawRectangle(Pen.Black, rect) Next

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

RectangleのOffsetメソッドを使うという方向なら Rectangleオブジェクトの生成は1回でいいことになります dim rect as new Rectangle( x, y, w, h ) for i = 0 to 10   g.DrawRectangle( Pens.Black. rect )   rect.Offset( 0, 1 ) next といった具合です …

その他の回答 (7)

  • MARU4812
  • ベストアンサー率43% (196/452)
回答No.8

> そうなんです。とてもできのいいプログラマの方は、グローバル変数だけでほとんどバグのでない ただ、一般企業の業務に使うような数万行のプログラムになってくると、 プログラム全体を把握する必要のあるような手法は、やはり不利に なるでしょう。 初見でも、引数や関数先頭の変数宣言で関数の全体像が分かるほうが いいと思います。 Sub や Function のコード行数を1画面に収めるって考え方も ありますよね。 (40行くらいまでに収めてしまって越える部分は別関数に) そうなってくると変数宣言は1箇所にまとまってくれてた 方が、私は気分的にwスッキリします。 局所的な変数は名称を自由に決めがちだし、むしろそういった 扱いなので、私の周りでは「関数内の変数宣言は関数先頭にまとめる」 傾向が強く残ってます。 ということで、私は変数宣言だけ外出し派です。 # インスタンスの生成は分かり易さ重視で、使いまわしが # できるのに使い捨て、毎回再作成でも許容範囲内ですね。 # もちろん、使いまわしできるならした方がいいですし、 # データ量が多く、目に見えるパフォーマンスに影響する # 場合は優先順位が変わりますが。

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.7

#3ですが、 #4さんのいうように >オブジェクト生成コストを減らすために#2さんのコードのように完全に外でnewして宣言する というのはそのほうがいいと私も思います。 イメージを示すためには dim rect0 as new Rectangle( x, y, w, h ) dim rect1 as new Rectangle( x, y*1, w, h ) ・・・ として、for~next内を rect = rect0 ・・・と書いたほうがよかったかなと途中から思ってはいました。 (といいつつ、#2さんのOffsetを使ったほうがよっぽどいいですが。) >というか、変数のスコープを絞ることがバグを減らすことに気づいていらっしゃらないようです というか、バグを増やす結果に陥る現実が隠れています。 >絞る必要が無いならグローバル変数だけでバグの少ないコードが書けるはずですよね? そうなんです。とてもできのいいプログラマの方は、グローバル変数だけでほとんどバグのでない プログラムを作ってしまいます。 (できの悪いプログラマが引き継いで、ボロボロにされてしまうことが多く、本当は、 悪い作り方なので、今どきはそういうことをする人は少ないですが。) 一方で、スコープを絞ったがために同じ目的の同じような変数を山のように作られて わけのわからないプログラムが出来上がってきたりすることが多々あるので、 下手にスコープを絞ることがバグの量産を導いてしまう現実がありました。 ## 私は両極端のプログラマしか見ていないのかも。 個人的には、subやfunction、メソッドetcの最初に使う変数をすべて列記しておくほうが みやすいソースであると思っていることも影響しているのかもしれません。 >複数使うことになったら関数化すべき というのも正しいとは思いますが、そうしてくれない人が多くって。 プロジェクトにできのいいプログラマさんが多ければ、本当は、 「好きに作れ。但し、バラバラはいやだからちゃんと統一するようにコミュニケーションとってね」 で終わりにしたいのですけど、夢物語なので。 最後に質問者様へ すみません。本来の質問から脱線してしまって申し訳ないです。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.6

#4ですが、私が#3さんのコードを意味が無いといったのはループの中でnewしているオブジェクトの受け手となる変数をループの外で用意することです。 この場合、変数のスコープを絞るために質問者様のコードのように完全に中でnewして宣言するか、オブジェクト生成コストを減らすために#2さんのコードのように完全に外でnewして宣言するかの二択で、外で宣言して中でnewするという手法は変数スコープの局所化的にもパフォーマンス的にもどっちつかずです。 というか、変数のスコープを絞ることがバグを減らすことに気づいていらっしゃらないようです(絞る必要が無いならグローバル変数だけでバグの少ないコードが書けるはずですよね?)し、 > Rectangleを複数使うとかしたときにややこしい(別々の変数をdimで宣言しようとするのかな?)。 という発言を見るに、変数のスコープを本当に理解していらっしゃるのか疑問です(この場合、For ~ Nextのブロックごと持っていけばいい。rectという変数名をいじる必要も無い。……が、複数使うことになったら関数化すべき)。 > その部分を移動したときに思わぬところでエラーがでる という問題点があるからこそ変数のスコープはなるべく絞るべきです。 まあ、私が#3さん主導のプロジェクトに所属していて > 私ならプログラム規約で禁止するでしょうね。 というなら従いますが。

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.5

ANo3です。 ANo4の方によると >For ~ Next の中での Dim宣言を行うのは という気色の悪いバグの温床のような書き方が、一般的なようです。 ということで、 >お行儀の悪い書き方。 という部分は取り消しておいてください。 "変数のスコープが実際に使用する箇所のみにする" という意図のようですが、 そもそも、1つのモジュール内で一部分のみにスコープしなければいけないこと自体、 プログラムの構造化に失敗しているしか思えませんし、 Rectangleを複数使うとかしたときにややこしい(別々の変数をdimで宣言しようとするのかな?)。 また、プログラム修正でその部分を移動したときに思わぬところでエラーがでる元になるだけ (まともなプログラマならエラー表示でるのですぐ分かるレベルでしょうが。)。 と思うのでANo4の方には悪いのですが私ならプログラム規約で禁止するでしょうね。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.4

時と場合によりますが、現在では一般的な書き方です。 なぜなら、変数のスコープが実際に使用する箇所のみにすることができるためです。 で、「時と場合」ですが、Rectangleが生成するのに非常に時間がかかる場合は生成をループ外に持っていく必要があります。 したがって、#3さんには悪いのですが、ループ内でnewしている#3さんの回答はそうする意味がない中途半端なものです。 生成以外には、ループ内では定数値になる計算や、同じファイルに追記するような場合のファイルオープン・クローズなど、時間とリソースを多分に使用してループ内では変化しないものに対する処理はループ外に持っていくのがパフォーマンス上一般的です。

  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.3

>For ~ Next の中での Dim宣言を行うのは お行儀の悪い書き方。 VB.net以降は動くみたいですけど、 Dim が「1 つまたは複数の変数を宣言し、記憶域を割り当てます。」 「」内はhttp://msdn.microsoft.com/ja-jp/library/7ee5a7s1(v=vs.80).aspx より。 というのを考えると、 For ~ Nextの間をこの場合10回繰り返すので、 同じ変数を10回宣言し、記憶域を10回割り当てます。 となる。(実際にはそうならないと思うが。) Dimは、ループの外で宣言すべきです。 Dim rect As Rectangle For i = 0 To 10   rect = new Rectangle(x, y* i , w, h)   g.DrawRectangle(Pen.Black, rect) Next とか書くべきでは?

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.1

フォームにPictureBoxを1つ貼り付け。またコマンドボタンを1つ貼り付け。コマンドボタンのクリックイベントに Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim x As Double = 10 Dim y As Double = 20 Dim w As Double = 20 Dim h As Double = 10 Dim g As Graphics = PictureBox1.CreateGraphics() For i = 0 To 10 Dim rect As New Rectangle(x, y * (i - 1) + 30, w, h) Dim p As New Pen(Color.Black, 1) g.DrawRectangle(p, rect) Next End Sub デバッグの開始 フォームのコマンドボタンをクリック、で 11個の四角(長方形)が縦に並んでできた。 質問のコードは大まか過ぎるでしよう。VB.Netは色々神経質な言語ですよね。 VBがよく判りすぎて、出来すぎて書くのを省略したのかな。

関連するQ&A

  • セルに対してFor Each~In~Nextを使う

    セルに対してFor Each~In~Nextを使う事は出来ない? シートやブックに対してループする時は Sub aaa() Dim w As Worksheet For Each w In Worksheets MsgBox w.Name Next End Sub 等を使いますが、 A1に「あ」 A2に「い」 A3に「う」 が入っている場合、 Sub bbb() Dim i As Long For i = 1 To Range("a65536").End(xlUp).Row MsgBox Cells(i, 1) Next End Sub で、全ての値を取得できますが、 For~to~nextではなく セルに対してFor Each~In~Nextを使う方法があれば教えてください。 上記のように Dim w As Worksheetは宣言できますが Dim c As Workcellとはできませんでした。 なぜわざわざFor~to~nextでできる事をFor Each~In~Nextでやりたいかと言うと、 シートやブックはFor~to~nextでできるのに、セルはFor~to~nextができない理由を知りたいからです。 ご回答よろしくお願いします。

  • For~Nextステートメント  途中で止めるには

    For~Nextステートメント で、変数が5なら止めたいのですがIFを使わない方法があったと思うのですが、 忘れてしまいました。 今は、 +++++++++++++++++++++++++++++ Sub test() Dim i As Long For i = 2 To 10 If i = 5 Then Stop End If Next End Sub +++++++++++++++++++++++++++++ としていますが、 If i = 5 Then Stop End If じゃなくても、一つのメソッドで出来た気がするのですが、 わかる方いらっしゃいますか? ご回答よろしくお願いします。

  • For next使う場合、next iはできない?

    vbsでFor next使う場合、next iはできないのですか? for i = 1 to 2 msgbox "" next i をすると "ステートメントの末尾が不正です"800A401 になります。 しかし for i = 1 to 2 msgbox "" next にすると、問題ないです。 VBAではnext iでも実行できるけどVBSではだめなのでしょうか? 理由を教えてください。

  • For ~ Next の使い方

    for ~ next 構文の途中でカウンターを進めることはできますか。 For I=1 to 10 処理 if ~ then next 処理 next このようにすると、エラーになります。 仕方なく次のようにしていますが、もっと良い方法はありますか。 For I=1 to 10 処理 if ~ then goto 次の行へ 処理 次の行へ: next

  • For~Nextについて

    VBA勉強中です。 For~Nextについて、いまいちわからないので、教えてほしいのですが、 下記の表を作り、テーブルと言う名前を付けました。 C列に上からA.Bの値を入れようと思います。 | A | B |C 1| AA| 11| 2| AB| 12| Sub Macro1() Dim AA As Range, BB As Range, AB As Variant Dim myTbl As Range, myFld As Integer, i As Integer Set AA = Range("A1") 'AAの箱にA1の値を Set BB = Range("B1") 'BBの箱にB1の値を Set myTbl = Range("テーブル") 'myTblの箱にテーブルを myFld = 3 'myFldの箱に3列目 AB = AA & "." & BB 'A1とB1の値を入れる For i = 1 To myTbl.Rows.Count 'iはテーブルの1行目から最後の行まで If myTbl.Cells(i, myFld).Value = AB Then 'テーブルの1行目のCのセルにA1とB1の値を入れる Exit Sub End If Next End Sub と思うのですが、やはり動きません。 アドバイスをお願いします。

  • 変数の宣言について

    VBですけれども 変数の宣言なしに For i  ・  ・   ・ Next i などを記述しますと「変数の宣言がされていません」 というメッセージがでるのですが、テキストなどでは 変数の宣言などしていなくとも動作しますこれはどうして どういうことなのかご存知の方教えてください。 Dimとかの宣言もなしにです。 著書は 独習Visual Basic 6.0 などです。

  • VB  FOR~NEXTについて

    下記の変数の宣言で、For w As Integer = 1 To 100 のWにチェックが付、デバックできません、考えられる点はどんな事があるのでしょうか? ご教授お願いします。 ' Button4のClickイベントを処理します。 Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click ' LineData用の変数です。 Dim cadLineData As New zwDrawCAD.LineData ' 線分の始点と終点を参照します。 Dim cadStartPoint As zwDrawCAD.DPoint = cadLineData.Start Dim cadEndPoint As zwDrawCAD.DPoint = cadLineData.End 'とりあえず線のセンターポイントは(100,100)にしてます。 Const X As Integer = 0 'cadStartPoint.x = 100 Const y As Integer = 0 'cadStartPoint.x = 100 Dim sr As System.IO.StreamReader = Nothing Try Dim file As String = TextBox1.Text 'SRとは New System.IO.StreamReaderの略 sr = New System.IO.StreamReader(file, System.Text.Encoding.GetEncoding("shift_jis")) Dim ansx As Double '計算された、xの座標 Dim ansy As Double '計算された、yの座標 Dim doc As String 'fileの1行 Dim x1 As String '1列目(X) Dim y2 As String '2列目(y)、 Dim x3 As String '3列目(X1)、 Dim y4 As String '4列目(y2) Dim angle As String '5列目(角度)、 Dim spare As String '6列目(予備)、 Dim item() As String ' Dim i As Integer '1行ずつテキストを読み取る doc = sr.ReadLine '1行読む Do Until IsNothing(doc) i += 1 item = doc.Split(",") 'カンマで区切る x1 = item(0) y2 = item(1) x3 = item(2) y4 = item(3) angle = item(4) spare = item(5) f2.data(x1, y2, x3, y4, angle, spare) f2.int(i) TextBox2.Text &= item(0) & " " & item(1) & " " & item(2) & " " & item(4) & " " & item(5) & " " & vbNewLine doc = sr.ReadLine '次の1行を読む Loop f2.println() Catch ex As Exception MessageBox.Show(ex.Message, "read") Finally If sr IsNot Nothing Then sr.Close() sr.Dispose() End If Dim len As Integer 'TextBox1に入力された線の長さ Dim angle As Double 'TextBox2に入力された角度 単位は度 Dim ansx As Double '計算された、xの座標 Dim ansy As Double '計算された、yの座標 '変数の宣言 Dim w As Integer Dim i As Integer '初期化 w = 0 i = 0 For w As Integer = 1 To 100 len = CDbl("x1" / 2) angle = CDbl(angle + 90) ansx = X + len * (Math.Cos(angle / 180 * Math.PI)) '終点のx座標 ansy = y + len * (Math.Sin(angle / 180 * Math.PI)) '終点のy座標 cadStartPoint.x = ansx * -1 cadStartPoint.y = ansy * -1 cadEndPoint.x = ansx cadEndPoint.y = ansy w = w + 1 Next End Try

  • For~Nextの使い方

    こんにちは Range("B19").Value = Application.WorksheetFunction.Sum(Range("B4:B17")) Range("B55").Value = Application.WorksheetFunction.Sum(Range("B40:B53")) Range("B91").Value = Application.WorksheetFunction.Sum(Range("B76:B89")) Range("B127").Value = Application.WorksheetFunction.Sum(Range("B112:B125")) 上記を参考書等で見ながらやって見たのですが 動作しません。 For~Nextの使い方を教えて下さい。 Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) Dim x As Long, g As Long For x = 19 To 127 Step 36 For g = 4 To 112 Step 36 Cells(x, "B").Value = Application.WorksheetFunction.Sum(Cells(g, "B")) Exit For Next Next End Sub

  • Excel 「For … Next」のやり方

    Excel画面のA1~A10を10~1の表示にさせるため、VBAを Sub ***() Worksheets("Sheet1").Activate Cells.Clear Dim i As Integer, n As Integer For i = 10 To 1 Step -1 Cells(i, 1).Value = i Next i End Sub としたのですが、実際に表示するとA1から1~10と1ずつ加算されてしまいます。 マイナス値は-1の表示で可能だといろいろ調べてわかったのですが、実際にやるとうまくいきません。 どこが間違っているのでしょうか? 学習不足ではありますが、よろしくお願いします。

  • Rectangle(Bitmap)の幅と高さ

     以下、VBの記法で書きます。Windows10,.NETのGDI+を使用しています。  今まであまり気にしていなかったのですが、今回LockBitsとUnLockBitsを使用してBitmapのpixel情報をCopyするコードを書く事になり、急に気になり出しました。  LockBitsを使用する際、Rectangle構造体で読みだすBitmapの範囲を指定します。Rectangleが指定する実際のpixelですが、   (Rectangle.Left + Rectangle.Width - 1)×(Rectangle.Top + Rectangle.Height - 1) の範囲かな?、と思いました。例えば、   Dim Rect as Rectangle = New Rectangle(1, 1, 0, 0) などとやると、Rectは空になるし、(1, 1)一点を表すRectangleなら、   Dim Rect as Rectangle = New Rectangle(1, 1, 1, 1) なので・・・。  BitmapのWidthとHeightについても同様かと思います。実際の動作には余り影響しないのですが、気になったもので・・・。

専門家に質問してみよう