やじゅ@アプリケーション・ラボ わんくま支局

目次

Blog 利用状況

ニュース

プロフィール

MSMVP

[VB]遅れてやってきたYield その4

これは、Visual Basic Advent Calendar 2012 12/18日の記事。

今回のYeildネタは、u_1rohさんの下記の記事を基にしている。

C# の yield return の使い道
http://d.hatena.ne.jp/u_1roh/20080302/1204471238
C# でイベントハンドラを yield return してみよう
http://d.hatena.ne.jp/u_1roh/20080909/1220937726

IEnumerator は下記のような状態遷移モデルで捉えることが出来る。

     MoveNext
●→○→○→○→◎

状態遷移モデルは結構実装が面倒でコードがぐちゃぐちゃになりやすい。
これを Yield を上手く使えば、状態遷移がすっきりと記述できる。

例として直線作図コマンド。
ビューを2点クリックされたら、その2点を結ぶ直線を作図する機能を見てみよう。
このコマンドは、次のような状態遷移図でモデル化できる。

起動     クリック   クリック   
●→クリック待ち→クリック待ち→直線描画

素直に組めば、クリックされた回数のカウント変数を用意したり、カウント値の偶数や奇数などで開始点や終了点を判断したり
するなど、「状態遷移」と「イベントドリブン」のコンボはスパゲッティコードの温床となりかねない。

Function Iterator 直線作図() As IEnumerator(Of 状態)
  Yield クリック待ち状態  '1点目のクリック待ち
  Yield クリック待ち状態  '2点目のクリック待ち
  直線オブジェクトを生成
End Function

これならクリック回数をカウントするような妙な変数を用意する必要がない。関心の分離が出来る。
関心の分離 http://ja.wikipedia.org/wiki/%E9%96%A2%E5%BF%83%E3%81%AE%E5%88%86%E9%9B%A2

C#で書かれたプログラムをVBで書き換えてみました。
VBで書き換える際に、悩んだところが「_handler.Current(Me, e)」で「式は値を生成しません」となってしまうこと。これはIEnumerator(Of MouseEventArgs) とすると値を返さないためコンパイルエラーとなってしまう。結局、DelegateTypeとして値を返すのを定義することで解決できた。

Public Class Form1
    ReadOnly _entities As New List(Of Action(Of Graphics))()
    Private Delegate Function DelegateType(sender As Object, e As MouseEventArgs) As Point
    Private _handler As IEnumerator(Of DelegateType)

    Public Sub New()
        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        _handler = Me.DrawLine()
        Me.MoveNext()
    End Sub

    Private Iterator Function DrawLine() As IEnumerable(Of DelegateType)
        While True
            Dim p1 As New Point()
            Dim p2 As New Point()

            Yield Function(sender, e) InlineAssignHelper(p1, e.Location)
            Yield Function(sender, e) InlineAssignHelper(p2, e.Location)
            _entities.Add(Sub(g) g.DrawLine(New Pen(Brushes.Black), p1, p2))
            Me.Invalidate()
        End While
    End Function
    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
        target = value
        Return value
    End Function
    Private Sub MoveNext()
        If Not _handler.MoveNext() Then
            _handler.Dispose()
            _handler = Nothing
        End If
    End Sub
    Private Sub Mouse_Click(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
        If _handler IsNot Nothing Then
            Dim result As Point
            result = _handler.Current(Me, e)
            Me.MoveNext()
        End If
    End Sub
    Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
        For Each draw In _entities
            draw(e.Graphics)
        Next
    End Sub
End Class

次回は、Yieldの特徴を利用してシューティングゲームの考察をしてみます。

投稿日時 : 2012年12月18日 23:28

コメントを追加

# ivermectin ebay http://stromectolabc.com/
ivermectin price usa 2022/02/08 2:42 Busjdhj

ivermectin ebay http://stromectolabc.com/
ivermectin price usa

# doxycycline generic https://doxycyline1st.com/
doxycycline pills 2022/02/26 8:17 Doxycycline

doxycycline generic https://doxycyline1st.com/
doxycycline pills

# 6 prednisone https://prednisone20mg.icu/ 2022/10/15 13:17 Prednisone

6 prednisone https://prednisone20mg.icu/

# meet singles for free https://datingtopreview.com/
free dating site chatting 2022/10/17 20:33 Dating

meet singles for free https://datingtopreview.com/
free dating site chatting

# dateing site https://topdatingsites.fun/
online love dating flash iframe 2022/11/15 0:23 DatingTop

dateing site https://topdatingsites.fun/
online love dating flash iframe

# over the counter ed pills https://overthecounter.pro/# 2023/05/08 18:12 OtcJikoliuj

over the counter ed pills https://overthecounter.pro/#

# ï»¿plavix generic https://plavix.guru/ Plavix 75 mg price 2023/10/23 21:14 Plavixxx

plavix generic https://plavix.guru/ Plavix 75 mg price

# prednisone pack https://prednisone.bid/ buy generic prednisone online 2023/12/27 6:52 Prednisone

prednisone pack https://prednisone.bid/ buy generic prednisone online

タイトル
名前
URL
コメント