LoginSignup
29
39

More than 5 years have passed since last update.

C#でUndo/Redoを実装した

Last updated at Posted at 2017-08-13

Undo/Redoを実装(C#)

UndoRedoIcon.png

C#で汎用的に使える(と思われる)Undo/Redoを実装したので紹介します.
アルゴリズムも後ろの方で紹介します.

環境

C# 6.0~が必要です.

ソース (GitHub)

こちら
理論はいいからともかく利用したいという方は上記リンクからダウンロードして, History.csを自分のプロジェクトに追加してください.

使い方

GitHubで公開しているサンプルコードを参考にして下さい.

(ぼくのかんがえたさいきょうの)アルゴリズム

内部でどんなことしてるのか知りたい人向けです.
ここのリビジョン:bd758f6e01c73fd7ea3ba6444d7441a59691275a
のソースコードをもとに説明します.

Commandパターンの利用

デザインパターンの一つであるCommandパターンを利用します.
メソッドの実行時にこれをインスタンスとして保存しておくことで,
「取り消す操作を実行する」「再び実行する」事が可能になります.

概念図

Overview.png

State(状態)とCommand(Undo/Redo操作)によるリンクリストになっています.



InitialState.png

初期段階では, 一つのStateだけが存在しています.

Record

実際に処理を実行し, Undo/Redo可能な操作として記録します.

Record.png

  • 処理を実行し, Commandを作成する
  • 新しいStateを作成し, 図のようなリンクリストを構築する
  • 追加されたStateに遷移する

Undo

Commandに記録しておいた「打ち消す処理」を実行します

Undo.png

  • 図のように「前のStateから遷移する時に実行されたCommand」のUndoを実行する
  • 前のStateに遷移する

Redo

次のStateへ遷移し, 登録しておいたCommandの処理を実行します

Redo.png

  • 「次のStateへ遷移する時に実行されるCommand」のDoを実行する
  • 次のStateへ遷移する

Record前にUndoしていたら

下の図のように, Undoしてから新たな処理を実行する場合は, 「次に遷移するStateがある状態」で新たなStateの作成をしなければなりません.

Overview.png

その場合, 現在より後ろのStateは全て破棄します.

RedoWhenUndone.png

Transaction

複数の操作を一つの操作としてまとめることもできます.
Commandの配列をもつCommandクラスを用意してあげれば良いですね.
詳細はTransactionCommandクラスを見てください.

TransactionCommand.png

余談

そもそもStateの存在可否から考えた方が良いかも知れない...
Commandの格納にQueueを使って, よりメモリ効率・実行速度の良い実装ができそうな気がしています.

お付き合い頂きありがとうございました.

29
39
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
39