SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Object型をツリー構造で管理するTreeElementクラス

ツリー構造をSystem.Collections.ArrayListクラスのように手軽に扱う

要素間の移動

 要素間の移動はコピーの操作とほとんど変わりません。

 ただ、コピーの場合はディープコピーが作成されていましたが、移動の場合は作成されずに要素自体が移動します。

MoveToメソッドの使用例
subChildElement.MoveTo( child1Element );

// ツリーの状態
// 
// Top
// Top/Child1
// Top/Child1/SubChild
// Top/Child2
// 

要素のリンク作成

 Windowsにはショートカットやハードリンクなど、要素へのリンクを表す便利な機能があります。CreateLinkElementメソッドを使用して要素自身のリンクを作成すると、これらと同等の機能を実現することができます。

 作成されたリンクからリンク先のTreeElementを取得したい場合は、Valueプロパティにアクセスします。

CreateLinkElementメソッドの使用例
TreeElement subChildLinkElement =
    subChildElement.CreateLinkElement();
child1Element.Add( subChildLinkElement );

// ツリーの状態
// 
// Top
// Top/Child1
// Top/Child1/<Link>SubChild
// Top/Child2
// Top/Child2/SubChild
// 

// リンク先の TreeElement を取得する
TreeElement linkReferenceElement =
    ( TreeElement )subChildLinkElement.Value;

// 
// linkReferenceElement.Name == "SubChild"
// 
補足
 リンク要素の名前には<Link>というプリフィックスがつきます。
 表示または非表示の切り替えは、IsVisibleLinkPrefixプロパティで設定できます。

foreachの使用

 TreeElementクラスは子要素へ簡単にアクセスする手段として、foreachに対応しています。

 ChildElementsプロパティやAllChildElementsプロパティの型であるTreeElementCollectionforeachに対応していますので、配下にあるすべての子要素にforeachでアクセスしたり、子要素にのみアクセスすることなどが簡単に行えます。

foreachの使用例
// topElement が次のようなツリー構造になっているものとします。
// 
// Top
// Top/Child1
// Top/Child1/SubChild1
// Top/Child1/SubChild2
// Top/Child2
// 

// TreeElement 自身を使用
foreach ( TreeElement childElement in topElement )
{
    Console.WriteLine( childElement.FullPath );
}

// 自身を含めたすべての要素へアクセス
// 
// Top
// Top/Child1
// Top/Child1/SubChild1
// Top/Child1/SubChild2
// Top/Child2
// 

// ChildElements プロパティを使用
foreach ( TreeElement childElement in topElement.ChildElements )
{
    Console.WriteLine( childElement.FullPath );
}

// 子要素のみへアクセス
// 
// Top/Child1
// Top/Child2
// 

// AllChildElements プロパティを使用
foreach ( TreeElement childElement in topElement.AllChildElements )
{
    Console.WriteLine( childElement.FullPath );
}

// すべての子要素へアクセス
// 
// Top/Child1
// Top/Child1/SubChild1
// Top/Child1/SubChild2
// Top/Child2
// 

TreeElementVisitor

TreeElementVisitorの概要
TreeElementVisitorの概要

 前述したように、TreeElementのみで階層構造をコードで表現しようとすると、読みにくいコードになったり無理が生じたりする場合があります。

 このような場合は、概要図のようにTreeElementのツリー構造内を前後に移動しながらアクセスするTreeElementVisitorを利用すると便利です。

 TreeElementVisitorはコンストラクタで設定されたTreeElementを開始位置として、MoveNextMovePreviousメソッドなどで構造内を移動します。現在位置のTreeElementにアクセスするにはCurrentElementプロパティを使用します。

 TreeElementVisitorクラスのメンバは次のとおりです。

TreeElementVisitorクラス図
TreeElementVisitorクラス図

TreeElementVisitorの使用例

 以下にTreeElementVisitorを開始位置とするTreeElementのインスタンスで初期化し、MoveNextメソッドとMovePreviousメソッドで移動しながら現在位置のTreeElementのパスを出力する例を示します。

TreeElementVisitorの使用例
// 次のようなツリー構造を持つ TreeElement 型の
// treeElement という変数が生成されていると仮定します。
// 
// Top
// Top/Child1
// Top/Child2
// Top/Child2/Child21
// Top/Child2/Child21/Child211
// Top/Child2/Child22
// Top/Child3
// Top/Child3/Child31
// 

// コンストラクタ
TreeElementVisitor visitor = new TreeElementVisitor( treeElement );

while( visitor.HasNext )
{
    // 次の要素へ移動
    visitor.MoveNext();
    Console.WriteLine( visitor.CurrentElement.FullPath );
}

// 出力結果
// 
// Top/Child1
// Top/Child2
// Top/Child2/Child21
// Top/Child2/Child21/Child211
// Top/Child2/Child22
// Top/Child3
// Top/Child3/Child31
// 

while( visitor.HasPrevious )
{
    // 前の要素へ移動
    visitor.MovePrevious();
    Console.WriteLine( visitor.CurrentElement.FullPath );
}

//  出力結果
// 
// Top/Child3
// Top/Child2/Child22
// Top/Child2/Child21/Child211
// Top/Child2/Child21
// Top/Child2
// Top/Child1
// Top
// 

 出力結果からMoveNextメソッドとMovePreviousメソッドはお互い逆方向の要素へ移動していることが分かると思います。

 移動手段としてこれらのメソッド以外にもMove( Int32 ):voidメソッドで数値を指定して前後へ移動したり、MoveUp():voidメソッドで親要素へ移動したり直感的に操作することができるメソッドを用意してあります。

まとめ

 今回のTreeElementの使用例では、ツリー構造を分かりやすくするために主にSystem.String型を使用しましたが、ValueプロパティはObject型なので汎用的な型を利用することができることから、.NETFrameworkクラスライブラリのSystem.Collections.ArrayListクラスのように、気軽にツリー構造を持つデータを表現することができます。

 詳しい内部処理などは「TreeElementソリューションファイル」内のソースコードをご覧ください。

参考資料

修正履歴

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

角尾 良太(カクオ リョウタ)

.NETの楽しさと力強さ、そしてJavaの美しさなど色々な観点からプログラミングの楽しさをたくさんの人と共有できたら良いなと願う.NETプログラマ。以下のサイトで制約モデルのテストやバリデーションに関するフレームワークライブラリを公開しています。 NKiwi Framework ライブラリ

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/435 2006/07/12 10:50

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー