実装8
実装8の内容は、「機械語の実行順序を利用者が変更できるようにする」です。これは、CommandListのItemsの並びを変えることで実現します。それにより実行順序が変更できるようになります。
この処理は一見簡単ですが、意外と間違えやすいので紙などに例を書いて確かめてみましょう。筆者も次の例を考えてから実装しました。
パターン1
INC INC DEC ←この命令を上げる。その後下げる DEC
INC DEC ←ここへこなければならない INC DEC
パターン2
INC ←この命令を上げる DEC MOV ADD
INC ←変化なしです。エラーが生じないかチェックしています DEC MOV ADD
パターン3
INC DEC MOV ADD ←この命令を下げる
INC DEC MOV ADD ←変化なしです。エラーが生じないかチェックしています
パターン4
DEC ←この命令を下に下げる。 INC ←この命令を下に下げる。 ADD MOV ※複数のアイテムを移動した場合です
ADD INC DEC MOV
このように複数のパターンを考えて見ましょう。特に、限界値チェックは大事です。一番上で上げる場合と一番下で下げる場合に注意が必要です。あと、単一アイテムの上下移動、複数アイテムの上下移動はチェックしておきましょう。これで処理の具体的イメージが固まったので実装します。
#Region "命令実行順序の操作" '選択した命令を一つ上へ移動します Private Sub UpButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UpButton.Click Dim count As Integer = Me.CommandList.SelectedItems.Count - 1 Dim target As Integer = 0 For i As Integer = 0 To count '選択されたアイテムの位置を取り出す Dim index As Integer = Me.CommandList.SelectedIndices(i) '選択された命令が0の場合もう上へ移動できない If index = 0 Then target = 1 Continue For End If '一つ上の命令と位置を交換する Dim tmp As Object = Me.CommandList.SelectedItems(i) Me.CommandList.Items.RemoveAt(index) Me.CommandList.Items.Insert(index - 1, tmp) Me.CommandList.SelectedItems.Add(tmp) Next End Sub '選択した命令を一つ下へ移動します Private Sub DownButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DownButton.Click Dim count As Integer = Me.CommandList.SelectedItems.Count - 1 For i As Integer = count To 0 Step -1 '選択されたアイテムの位置を取り出す Dim index As Integer = Me.CommandList.SelectedIndices(i) '選択された命令が最大値の場合もう下へ移動できない If index = Me.CommandList.Items.Count - 1 Then Continue For End If '一つ上の命令と位置を交換する Dim tmp As Object = Me.CommandList.SelectedItems(i) Me.CommandList.Items.RemoveAt(index) Me.CommandList.Items.Insert(index + 1, tmp) Me.CommandList.SelectedItems.Add(tmp) Next End Sub #End Region
この実装のポイントは、SelectedItemsプロパティとSelectedIndicesプロパティの使い方です。SelectedItemsプロパティには、選択されたオブジェクトが格納されており、SelectedIndicesプロパティには選択されたオブジェクトの位置(インデックス)が格納されています。この2つのプロパティをうまく使うことにより実装が簡単になります。
この例のように既存の機能をうまく使いこなすのが実務でのテクニックです。趣味プログラミングでは、オリジナルのオブジェクトを実装したり、冗長な実装をしても咎められることがありません。しかし、実務では「他の人が見ても分かるか」(可読性)も重視されますので、日頃からMSDNをチェックしたり、実装をする前に「その機能は既にないか」調べる癖を身につけましょう。
他に注意するべき所は、「一つ上の命令と位置を交換する」と「一つ上の命令と位置を交換する」のアイテムの交換部分です。交換は一旦選択されたアイテムを消して、後で適切な位置へ挿入することにより行います。これはプログラミング特有の考え方であり、初心者の方はイメージしにくいと思いますので筆者のイメージを書きます。まず本はぎっしり並んでいる本棚をイメージします。この場合本を並び替えるには、一旦本を取り出さなくてはなりません(RemoveAt)、そして適切な位置へ本を戻します(Insert)。このイメージでコードを見ると分かりやすいかと思います。
なお、SelectedItems.Add(tmp)の部分ですが、これは視覚的な問題を解決するためのコードです。このコードをコメントアウトしても正しく並びかえられます。しかし、フォーカスが消えてしまいます。そこでこのコードを書きました。このコードがなくても仕様的には問題はありませんが、この様な配慮をするのが実務ではベストです。ただし、実務では勝手に余計な処理を書いてはならないので、ちゃんと確認を取りましょう。十分に注意してください。
まとめ
いかがだったでしょうか? 今回は前回課題として書いた機械語駆動式関数電卓の実装例を半分解説しました。残り半分は次回書きます。皆さまは無事解けましたか? 初心者の方は実装できなかった部分もあると思いますが、慣れが必要なので気にしないでください。一方上級者の方は物足りなかったかもしれません。そのような方は、ぜひ仕様を追加してください。浮動小数点や計算式の解析機能まで追加すれば面白いと思います。次回で機械語駆動式関数電卓の残りの実装を解説します。お楽しみに。
