メソッドの使い分けについて

解決


九十九  2009-10-13 11:50:20  No: 146372  IP: 192.*.*.*

メソッドには、subとFunctionがありますが、どちらを使えばよいのか
わからないことがあります。戻り値の有無と説明されてますが、
その戻り値についても判断しかねる場合が多々あります。

下記は、タイピングゲームを作ってみたのですが、いちおうsubメソッドで
作成しました。

これをFunctionでも記述できると思うのですが、その場合の記述の仕方が
今ひとつ理解が及びません。できれば、ご教授お願いします。



(ファイルをLabel1に読み込み全文を確認してから、スタートを押すと
  テキストボックスに1行ずつ文字列が表示されます。
  ストップでタイピングに要した時間が表示されます。)
Imports System.IO, System.Text
Public Class Form1
    Dim count As Integer
    Dim total As Integer
    Dim fname As String
    Dim n As Integer = -1
   
 ’スタートボタン
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextBox4.Visible = True
        Label1.Visible = False
        If Label1.Text = "" Then
            MessageBox.Show("ファイルを読み込んでください")
        Else
            mondai()
          
         End If
    End Sub

’ストップボタン
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Timer1.Stop()
        TextBox2.Text = total.ToString & "秒です"
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        count += 1
        total = count



    End Sub

’問題文を1行ずつ表示するメソッド
    Private Sub mondai()
        TextBox1.Focus()
        ImeModeBase = Windows.Forms.ImeMode.Hiragana
        count = 0
        Timer1.Start()
        TextBox1.Text = ""
        TextBox2.Text = ""

        Dim line As Integer
        line = File.ReadAllLines(fname).Length
        Dim str(line - 1) As String
        Dim sr As StreamReader = New StreamReader(fname, Encoding.Default)
        n += 1

        For i As Integer = 0 To n
            If i < line Then
                str(i) = sr.ReadLine
                TextBox4.Text = str(i)
            Else
                n = -1

            End If
        Next


        sr.Close()
    End Sub
   
 'ファイルをLabel1に読み込む
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        TextBox4.Visible = False
        Label1.Visible = True
        If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
            Label1.Text = System.IO.File.ReadAllText(OpenFileDialog1.FileName, Encoding.Default)
            fname = OpenFileDialog1.FileName
        End If
    End Sub
End Class

編集 削除
特攻隊長まるるう  2009-10-13 12:53:22  No: 146373  IP: 192.*.*.*

> その戻り値についても判断しかねる場合が多々あります。
具体性が無い記述なので意味が理解できません。

何をどう判断しようとして、どんな場合になぜ判断しかねているのですか?

編集 削除
九十九  2009-10-13 13:11:05  No: 146374  IP: 192.*.*.*

早速のレス感謝します。

>具体性が無い記述なので意味が理解できません。

すみません。

例えば上記の場合は、各行の問題文が戻り値になると思うのですが
違うのですか?

編集 削除
特攻隊長まるるう  2009-10-13 13:30:44  No: 146375  IP: 192.*.*.*

> 例えば上記の場合は、各行の問題文が戻り値になると思うのですが
> 違うのですか?
仕様次第でしょう。つまりプログラマがどう作るかを決めます。
関数内でエラーが起こったら False を返すでも良いのでは?

もともとプログラムというものに正解などありません。
どう作っても構いません。
判断基準は仕様(要望)を満たしているかどうかです。

編集 削除
九十九  2009-10-13 14:03:50  No: 146376  IP: 192.*.*.*

>もともとプログラムというものに正解などありません。
>どう作っても構いません。
>判断基準は仕様(要望)を満たしているかどうかです。

有り難いお言葉です。

タイピングゲームは、とある本のサンプルですが、オブジェクト指向
で書かれていたので、自分なりに書き直してみたものです。
オブジェクト指向は考え方としては、理解しやすいプログラミングの技法
なのでしょう。しかし、私のように一人でちまちまと趣味でやる人間にとってはあまり必要ではないと思っています。

編集 削除
特攻隊長まるるう  2009-10-13 15:02:12  No: 146377  IP: 192.*.*.*

> しかし、私のように一人でちまちまと趣味でやる人間にとってはあまり必要ではないと思っています。
その意見には賛同しかねます。

> 理解しやすいプログラミングの技法
とおっしゃるなら、参考にすべきでは?他人にとってと言うことでしょうか?他人にとって
理解しやすいのであれば、自分の頭の中を整理するのに役立つでしょう。
また、公共の場である質問掲示板で質問している時点で、他人に説明する力が必要になります。
ならば、むしろ積極的に取り入れるべきという結論になりそうなものですが?

結局、戻り値の話がどこかに行ってしまいましたが。。。
繰り返しますが、
> 何をどう判断しようとして、どんな場合になぜ判断しかねているのですか?

編集 削除
九十九  2009-10-13 15:39:09  No: 146378  IP: 192.*.*.*

>他人にとって理解しやすいのであれば、自分の頭の中を整理するのに役立つ>でしょう。
>また、公共の場である質問掲示板で質問している時点で、他人に説明する力>が必要になります。
>ならば、むしろ積極的に取り入れるべきという結論になりそうなものですが

確かにその通りだと思います。
ただ、いろいろと表記の仕方が面倒というか、消化しきれていないからなのでしょう。オブジェクト指向は、今後少しずつ勉強していきたいと思います。

> 何をどう判断しようとして、どんな場合になぜ判断しかねているのですか?

戻り値という概念が理解できていないのかもしれません。

メソッドをFunctionにして下記のように書き直してみましたが
これでは、要素数を超える回数をクリックすると「インデックスが配列の境界外です。」というエラーをはきます。






Imports System.IO, System.Text
Public Class Form1
    Dim count As Integer
    Dim total As Integer
    Dim fname As String
    Dim n As Integer = -1
    Dim i As Integer
   

 ’スタート
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextBox4.Visible = True
        Label1.Visible = False
        If Label1.Text = "" Then
            MessageBox.Show("ファイルを読み込んでください")
        Else
            mondai(i)
         
        End If
    End Sub


’ストップ
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Timer1.Stop()
        TextBox2.Text = total.ToString & "秒です"
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        count += 1
        total = count



    End Sub


'問題文を表示するメソッド   
 Function mondai(ByVal i As Integer) As String

        TextBox1.Focus()
        ImeModeBase = Windows.Forms.ImeMode.Hiragana
        count = 0
        Timer1.Start()
        TextBox1.Text = ""
        TextBox2.Text = ""

        Dim line As Integer
        line = File.ReadAllLines(fname).Length
        Dim str(line - 1) As String
        Dim sr As StreamReader = New StreamReader(fname, Encoding.Default)
        n += 1

        For i = 0 To n
            If i < line Then
                str(i) = sr.ReadLine
                TextBox4.Text = str(i)
            Else
                n = -1

            End If
        Next


        sr.Close()
        Return str(i)

    End Function
 

   'ファイルをLabel1に読み込む
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        TextBox4.Visible = False
        Label1.Visible = True
        If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
            Label1.Text = System.IO.File.ReadAllText(OpenFileDialog1.FileName, Encoding.Default)
            fname = OpenFileDialog1.FileName
        End If
    End Sub
End Class

編集 削除
特攻隊長まるるう  2009-10-13 16:15:53  No: 146379  IP: 192.*.*.*

> メソッドをFunctionにして下記のように書き直してみましたが
> これでは、要素数を超える回数をクリックすると「インデックスが配列の境界外です。」というエラーをはきます。
定時のコードで戻り値は使ってないわけですし、普通にバグなのでデバッグしてください。

編集 削除
特攻隊長まるるう  2009-10-13 16:17:18  No: 146380  IP: 192.*.*.*

失礼。誤字です。
×定時
  ↓
○提示

編集 削除
九十九  2009-10-13 18:05:14  No: 146381  IP: 192.*.*.*

簡単な例で申し訳ないのですが、数を2倍にするメソッドを作ってみました。
下記のコードでは、subでもFunctionでもどちらも結果は同じになります。
ということはこの場合はどちらでも良いという結論で良いのですか?

この2つのメソッドを使い分ける判断というか切り分けが知りたいのです。

 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        sbaisuu(4)

    End Sub
    Private Sub sbaisuu(ByVal i As Integer)

        TextBox1.Text = (i * 2).ToString

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Fbaisuu(4)
    End Sub
    Function Fbaisuu(ByVal i As Integer) As Integer
        TextBox2.Text = (i * 2).ToString
        Return i

    End Function

編集 削除
ひよこ  2009-10-13 18:09:03  No: 146382  IP: 192.*.*.*

関数を呼び出して、そのなかで処理が完結するならばSubを使えば
いいのではないでしょうか。

呼び出された関数で処理をして、その結果を呼び出し側の処理で
必要ならFunctionを使えばいいと思います。

最初の投稿されているコードにではmondaiを呼び出すところで
引数もないようですし、呼び出したあとで、呼び出し側で処理も
していないので、Functionを使う必要はないようにおもいます。

次に投稿されたコードでは引数としてiを渡していますが
For文のところで初期化されてしまっていますよね。
Functionを使うために渡しているんでしょうか?
Functionを使うときでも別に引数も戻り値もなくても、問題なかった
と思います。
まあ、それならSubを使えってことになるんですが、、、

編集 削除
ひよこ  2009-10-13 18:32:06  No: 146383  IP: 192.*.*.*

>Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As >System.EventArgs) Handles Button2.Click
>        Fbaisuu(4)
>    End Sub
>    Function Fbaisuu(ByVal i As Integer) As Integer
>        TextBox2.Text = (i * 2).ToString
>        Return i

>    End Function




Fbaisuuを呼び出してるほうで戻り値を受け取ってないですし
それを使って処理もしてないので(SubもFunctionも関数のなかで
テキストボックスへ表示してるので)結果は同じだと思います

もしFunctionを使う練習なら
計算だけFbaisuuで行って、その戻り値を受け取って、
 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
のなかでテキストボックスへの表示を行ってみてはいかかでしょう。

編集 削除
九十九  2009-10-13 19:14:07  No: 146384  IP: 192.*.*.*

ひよこさん、すみません。
こんな感じですか?

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        TextBox2.Text = Fbaisuu(4).ToString
    End Sub
    Function Fbaisuu(ByVal i As Integer) As Integer
        Dim k As Integer = i * 2
        Return k
    End  Function

編集 削除
特攻隊長まるるう  2009-10-13 19:25:07  No: 146385  IP: 192.*.*.*

おぉ。すごい!TextBox1 の処理も同じ関数で書ける!
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextBox1.Text = Fbaisuu(4).ToString
    End Sub

編集 削除
ひよこ  2009-10-13 19:31:12  No: 146386  IP: 192.*.*.*

あら、いいところをまるるさんに。。。(笑

あとは、上記のコードで思ったとおりの動きが出来ている
と思うので、特にいうこともないでしょう。
関数のいいところもまるるうさんの投稿でおわかりでしょうし。

これで、問題は解決されたでしょうか。

編集 削除
九十九  2009-10-13 19:46:21  No: 146387  IP: 192.*.*.*

>これで、問題は解決されたでしょうか

何とか見えてきたように思います。
今後さらに学びを深めていきたいと思っていまが
行き詰まったら、またご助言を仰ぎたいと思っていますので
よろしくお願いします。

特攻隊長まるるうさん、 ひよこさん、本当に有り難うございました。

編集 削除
九十九  2009-10-13 19:47:57  No: 146388  IP: 192.*.*.*

誤字がありましたので訂正します。失礼しました。

>これで、問題は解決されたでしょうか

何とか見えてきたように思います。
今後さらに学びを深めていきたいと思っていますが
行き詰まったら、またご助言を仰ぎたいと思っていますので
よろしくお願いします。

特攻隊長まるるうさん、 ひよこさん、本当に有り難うございました。

編集 削除
おばか。  2009-10-14 10:08:57  No: 146389  IP: 192.*.*.*

本を買うことは、単に勉強だけの話ではない。
Visual製品は、きちんと正式に稼動しているか検査もできる。
ニセもの製品だと動かないコードがあるかもね。

編集 削除