C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2007/10/08 21:38
仮想プロキシによるレイジーロード ( PofEAA ) を実装する際に利用できる、汎用的な仮想リスト及び仮想リストローダーを C# で書いてみました。 ( 特に変わったことはしてません。単に、コードを記録する目的で記事にしました。 )

仮想リストは、実装すべきインターフェイスが多いためコード量が多くなっていますが、重要なのは Items プロパティだけです。他のプロパティやメソッドは全て、Items プロパティから取得したリストに処理を委譲しているだけです。

VirtualList<T> クラス
using System;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// リストの仮想プロキシです。
/// </summary>
/// <typeparam name="T"></typeparam>
[Serializable]
public sealed class VirtualList<T> : IList<T>
{
    #region Constructors

    /// <summary>
    /// VirtualList&lt;T> クラスの新しいインスタンスを初期化します。
    /// </summary>
    /// <param name="loader">ローダー。</param>
    /// <exception cref="System.ArgumentNullException">引数 loader が null です。</exception>
    public VirtualList(IListLoader<T> loader)
    {
        if (loader == null)
        {
            throw new ArgumentNullException("loader");
        }
        this._items = null;
        this._loader = loader;
    }

    #endregion

    #region Fields

    /// <summary>
    /// ソースリストを取得または設定します。
    /// </summary>
    private IList<T> _items;

    /// <summary>
    /// ローダーを取得します。
    /// </summary>
    private readonly IListLoader<T> _loader;

    #endregion

    #region Properties

    /// <summary>
    /// ソースリストを取得します。
    /// </summary>
    private IList<T> Items
    {
        get
        {
            if (this._items == null)
            {
                this._items = this._loader.Load();
            }
            return this._items;
        }
    }

    #endregion

    #region IList<T> メンバ

    /// <summary>
    /// 指定したインデックスにある要素を取得または設定します。
    /// </summary>
    /// <param name="index">取得または設定する要素の、0 から始まるインデックス番号。</param>
    /// <returns>指定したインデックスにある要素。</returns>
    /// <exception cref="System.NotSupportedException">このプロパティが設定されていますが、VirtualList&lt;T> が読み取り専用です。</exception>
    /// <exception cref="System.ArgumentOutOfRangeException">index が VirtualList&lt;T>  の有効なインデックスではありません。</exception>
    public T this[int index]
    {
        get
        {
            return this.Items[index];
        }
        set
        {
            this.Items[index] = value;
        }
    }

    /// <summary>
    /// VirtualList&lt;T> 内での指定した項目のインデックスを調べます。
    /// </summary>
    /// <param name="item">IList&lt;T> 内で検索するオブジェクト。</param>
    /// <returns>リストに存在する場合は item のインデックス。それ以外の場合は -1。</returns>
    public int IndexOf(T item)
    {
        return this.Items.IndexOf(item);
    }

    /// <summary>
    /// VirtualList&lt;T> の指定したインデックス位置に項目を挿入します。
    /// </summary>
    /// <param name="index">VirtualList&lt;T> に挿入するオブジェクト。</param>
    /// <param name="item">item を挿入する位置の、0 から始まるインデックス番号。</param>
    /// <exception cref="System.NotSupportedException">VirtualList&lt;T> は読み取り専用です。</exception>
    /// <exception cref="System.ArgumentOutOfRangeException">index が VirtualList&lt;T> の有効なインデックスではありません。</exception>
    public void Insert(int index, T item)
    {
        this.Items.Insert(index, item);
    }

    /// <summary>
    /// 指定したインデックス位置の VirtualList&lt;T> 項目を削除します。
    /// </summary>
    /// <param name="index">削除する項目の 0 から始まるインデックス。</param>
    /// <exception cref="System.NotSupportedException">VirtualList&lt;T> は読み取り専用です。</exception>
    /// <exception cref="System.ArgumentOutOfRangeException">index が VirtualList&lt;T> の有効なインデックスではありません。</exception>
    public void RemoveAt(int index)
    {
        this.Items.RemoveAt(index);
    }

    #endregion

    #region ICollection<T> メンバ

    /// <summary>
    /// VirtualList&lt;T> に格納されている要素の数を取得します。
    /// </summary>
    public int Count
    {
        get
        {
            return this.Items.Count;
        }
    }

    /// <summary>
    /// VirtualList&lt;T> が読み取り専用かどうかを示す値を取得します。
    /// </summary>
    public bool IsReadOnly
    {
        get
        {
            return this.Items.IsReadOnly;
        }
    }

    /// <summary>
    /// VirtualList&lt;T> に項目を追加します。
    /// </summary>
    /// <param name="item">VirtualList&lt;T> に追加するオブジェクト。</param>
    /// <exception cref="System.NotSupportedException">VirtualList&lt;T> は読み取り専用です。</exception>
    public void Add(T item)
    {
        this.Items.Add(item);
    }

    /// <summary>
    /// VirtualList&lt;T> からすべての項目を削除します。
    /// </summary>
    /// <exception cref="System.NotSupportedException">VirtualList&lt;T> は読み取り専用です。</exception>
    public void Clear()
    {
        this.Items.Clear();
    }

    /// <summary>
    /// VirtualList&lt;T> に特定の値が格納されているかどうかを判断します。
    /// </summary>
    /// <param name="item">VirtualList&lt;T> 内で検索するオブジェクト。</param>
    /// <returns>item が VirtualList&lt;T> に存在する場合は true。それ以外の場合は false。</returns>
    public bool Contains(T item)
    {
        return this.Items.Contains(item);
    }

    /// <summary>
    /// VirtualList&lt;T> の要素を System.Array にコピーします。System.Array の特定のインデックスからコピーが開始されます。
    /// </summary>
    /// <param name="array">VirtualList&lt;T> から要素がコピーされる 1 次元の System.Array。System.Array には、0 から始まるインデックス番号が必要です。</param>
    /// <param name="arrayIndex">コピーの開始位置となる、array の 0 から始まるインデックス番号。</param>
    /// <exception cref="System.ArgumentException">
    /// array が多次元です。
    /// またはarrayIndex が array の長さ以上です。
    /// またはコピー元の VirtualList&lt;T> の要素数が、arrayIndex からコピー先の array の末尾までに格納できる数を超えています。
    /// または型 T をコピー先の array の型に自動的にキャストすることはできません。
    /// </exception>
    /// <exception cref="System.ArgumentNullException">array が null です。</exception>
    /// <exception cref="System.ArgumentOutOfRangeException">arrayIndex が 0 未満です。</exception>
    public void CopyTo(T[] array, int arrayIndex)
    {
        this.Items.CopyTo(array, arrayIndex);
    }

    /// <summary>
    /// VirtualList&lt;T> 内で最初に見つかった特定のオブジェクトを削除します。
    /// </summary>
    /// <param name="item">VirtualList&lt;T> から削除するオブジェクト。</param>
    /// <returns>
    /// item が VirtualList&lt;T> から正常に削除された場合は true。それ以外の場合は false。
    /// このメソッドは、item が元の VirtualList&lt;T> に見つからない場合にも false を返します。
    /// </returns>
    /// <exception cref="System.NotSupportedException">VirtualList&lt;T> は読み取り専用です。</exception>
    public bool Remove(T item)
    {
        return this.Items.Remove(item);
    }

    #endregion

    #region IEnumerable<T> メンバ

    /// <summary>
    /// コレクションを反復処理する列挙子を返します。
    /// </summary>
    /// <returns>コレクションを反復処理するために使用できる System.Collections.Generic.IEnumerator&lt;T>。</returns>
    public IEnumerator<T> GetEnumerator()
    {
        return this.Items.GetEnumerator();
    }

    #endregion

    #region IEnumerable メンバ

    /// <summary>
    /// コレクションを反復処理する列挙子を返します。
    /// </summary>
    /// <returns>コレクションを反復処理するために使用できる System.Collections.IEnumerator オブジェクト。</returns>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((System.Collections.IEnumerable)this.Items).GetEnumerator();
    }

    #endregion
}


IListLoader<T> インターフェイス
using System;
using System.Collections.Generic;

/// <summary>
/// リストのローダーです。
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IListLoader<T>
{
    /// <summary>
    /// リストをロードします。
    /// </summary>
    /// <returns>リスト。</returns>
    IList<T> Load();
}


この仮想リスト及びローダーは、そのまま使用できます。
仮想リストはシールクラスにしてあります。これは、仮想リストを継承したクラスを定義する必要がないはずだからです。null を許可しないとか重複を許可しないといった制約は、仮想リストには実装しません。


この仮想リスト及びローダーを使用したレイジーロードの実装例は次回にでも。


// 追記 (2010/06/06)
Lazy クラスを使用した仮想プロキシを実装してみました。


よこけんさん こんにちは
イルカのジョナサンといいます

当方プログラマーではありませんが
あるプログラムのために C++の勉強をしています
そのプログラム?を ビルド? したいのですが
うまくいきません
どうしても 動かしたい ソフトがあり
それを うごかすために
ここにたどりつきました。

ヒントだけでもおしえていただくとうれしいです。(^ ^;)

2007.10.09 11:38 URL | イルカのジョナサン #RKfjDPUo [ 編集 ]


イルカのジョナサンさん、はじめまして^^

イルカのジョナサンさんがお書きになられたプログラムの、ビルドが失敗してしまうということでしょうか?

プログラムは決まった文法に従って書かなければいけません。C++ならC++の文法に従わなければなりません。文法に従っていないプログラムをビルドしようとしても、「ビルドエラー」が発生して失敗してしまいます。また、例え文法に従っていても、必要なファイルが足りていないといった理由で失敗する場合もあります。
大抵の場合、発生したビルドエラーのエラーメッセージを読めば原因がわかります。

今回、イルカのジョナサンさんがどのようなプログラムを書いているのかはわからないのと、C++は私の専門外ということもあり、申し訳ないのですがこれ以上の助言はできません。

私のブログにはありませんが、インターネット上には、プログラミングの質問掲示板があります。自力で解決できそうにないのであれば、そういった掲示板で質問してみると良いと思います。
その際、以下の点を可能な限り明記すると、回答者の方が答えやすいと思います。

・プログラム言語(今回はC++)
・プログラム言語のバージョン(例:MC++8.0)
・開発環境(例:Visual Studio 2005 Professional Edition)
・OS(例:Windows XP Professional Edition SP2)
・どんなことをしようとしているか(例:テキストボックスに入力したファイル名のファイルの内容を表示しようとしている)
・エラーの内容(例:クラス FileStream が見つかりません。)
・プログラム内でエラーが発生した箇所がわかれば、その周辺のプログラム(例:FileStream stream = new FileStream();の箇所でエラー)
・問題解決の為に試してみたこと(例:○○を試してみたけど××となってしまってダメだった)


せっかくコメントして頂いたのに、あまりお役に立てずすみません・・・。

2007.10.09 23:52 URL | よこけん #Ay6tTHf6 [ 編集 ]


イルカのジョナサンさん、こんばんわ

力になれませんでしたが、問題が解決したようで良かったです^^

2007.10.15 23:03 URL | よこけん #Ay6tTHf6 [ 編集 ]












トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/167-440f4e74