こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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

投稿日時 - 2011-10-22 11:33:37

QNo.7087018

すぐに回答ほしいです

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

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
といった具合です …

投稿日時 - 2011-10-23 00:19:56

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.8

> そうなんです。とてもできのいいプログラマの方は、グローバル変数だけでほとんどバグのでない
ただ、一般企業の業務に使うような数万行のプログラムになってくると、
プログラム全体を把握する必要のあるような手法は、やはり不利に
なるでしょう。
初見でも、引数や関数先頭の変数宣言で関数の全体像が分かるほうが
いいと思います。

Sub や Function のコード行数を1画面に収めるって考え方も
ありますよね。
(40行くらいまでに収めてしまって越える部分は別関数に)
そうなってくると変数宣言は1箇所にまとまってくれてた
方が、私は気分的にwスッキリします。

局所的な変数は名称を自由に決めがちだし、むしろそういった
扱いなので、私の周りでは「関数内の変数宣言は関数先頭にまとめる」
傾向が強く残ってます。
ということで、私は変数宣言だけ外出し派です。

# インスタンスの生成は分かり易さ重視で、使いまわしが
# できるのに使い捨て、毎回再作成でも許容範囲内ですね。
# もちろん、使いまわしできるならした方がいいですし、
# データ量が多く、目に見えるパフォーマンスに影響する
# 場合は優先順位が変わりますが。

投稿日時 - 2011-10-25 11:44:42

ANo.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の最初に使う変数をすべて列記しておくほうが
みやすいソースであると思っていることも影響しているのかもしれません。

>複数使うことになったら関数化すべき
というのも正しいとは思いますが、そうしてくれない人が多くって。

プロジェクトにできのいいプログラマさんが多ければ、本当は、
「好きに作れ。但し、バラバラはいやだからちゃんと統一するようにコミュニケーションとってね」
で終わりにしたいのですけど、夢物語なので。

最後に質問者様へ
すみません。本来の質問から脱線してしまって申し訳ないです。

投稿日時 - 2011-10-24 23:52:45

ANo.6

#4ですが、私が#3さんのコードを意味が無いといったのはループの中でnewしているオブジェクトの受け手となる変数をループの外で用意することです。
この場合、変数のスコープを絞るために質問者様のコードのように完全に中でnewして宣言するか、オブジェクト生成コストを減らすために#2さんのコードのように完全に外でnewして宣言するかの二択で、外で宣言して中でnewするという手法は変数スコープの局所化的にもパフォーマンス的にもどっちつかずです。

というか、変数のスコープを絞ることがバグを減らすことに気づいていらっしゃらないようです(絞る必要が無いならグローバル変数だけでバグの少ないコードが書けるはずですよね?)し、
> Rectangleを複数使うとかしたときにややこしい(別々の変数をdimで宣言しようとするのかな?)。
という発言を見るに、変数のスコープを本当に理解していらっしゃるのか疑問です(この場合、For ~ Nextのブロックごと持っていけばいい。rectという変数名をいじる必要も無い。……が、複数使うことになったら関数化すべき)。
> その部分を移動したときに思わぬところでエラーがでる
という問題点があるからこそ変数のスコープはなるべく絞るべきです。

まあ、私が#3さん主導のプロジェクトに所属していて
> 私ならプログラム規約で禁止するでしょうね。
というなら従いますが。

投稿日時 - 2011-10-24 00:26:06

ANo.5

ANo3です。
ANo4の方によると
>For ~ Next の中での Dim宣言を行うのは
という気色の悪いバグの温床のような書き方が、一般的なようです。
ということで、
>お行儀の悪い書き方。
という部分は取り消しておいてください。

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

投稿日時 - 2011-10-23 16:42:15

ANo.4

時と場合によりますが、現在では一般的な書き方です。
なぜなら、変数のスコープが実際に使用する箇所のみにすることができるためです。

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

投稿日時 - 2011-10-23 03:30:43

ANo.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
とか書くべきでは?

投稿日時 - 2011-10-23 01:30:21

ANo.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がよく判りすぎて、出来すぎて書くのを省略したのかな。

投稿日時 - 2011-10-22 21:52:31

あなたにオススメの質問