3

配列は、順序付けされていないアイテムのセットを反復処理するための高速な方法であり、多くの場合、読み取り専用であると便利です。配列の内容は変更される可能性があるため、「readonly」キーワードで配列を公開しても意味がありませんが、ReadOnlyCollection<T> ラッパーがこれを解決します。問題は、私が行ったテストでは、単純な配列よりも 4 倍遅いことです。(配列のコピーを返すと、パフォーマンスが低下するのは 1 回だけですが、理想的には、そのために CPU 時間を無駄にしたくありません。)

次のようなクラスを持つプレーン配列のパフォーマンスを維持しながら、読み取り専用の健全性チェックの利点を得ることができることに気付きました。

class ReadOnlyArray<T>
{
    private readonly T[] array;

    public ReadOnlyArray(T[] a_array)
    {
        array = a_array;
    }

    // read-only because no `set'
    public T this[int i]
    { get { return array[i]; } }

    public int Length
    { get { return array.Length; } }
}

問題は、foreach() 構文の便利さを失っていることです。つまり、パフォーマンスを維持するために for(;;) ループで反復する必要があります。-- 以前は、すべてのループが for(;;) である C コードを書いていました。甘やかされてしまったのかな。-- IEnumerable<T> を実装すると、ReadOnlyCollection<T> と同じパフォーマンスが得られますが、このクラスは役に立ちません。

読み取り専用のサニティ チェック、パフォーマンスの低下なし、便利な foreach() 構文という 3 つの目標すべての完璧な組み合わせを達成する方法はありますか?

4

2 に答える 2

4

以下はあなたが望むことをすると思います。しかし、これは実際にはお勧めできないと思います。不必要で混乱を招く可能性のある抽象化を課しています。はい、おそらく最終的には JIT によって最適化されるので、同僚もそれに追いつくはずです。しかし、言語が意図していないことをまだ行っています。

編集:以下のコードを微調整してよりよく説明し、いくつかのオプションについて言及しました。

using System.Collections;
using System.Collections.Generic;

/*
  You can leave off the interface, or change to IEnumerable.  See below.
*/
class ReadOnlyArray<T> : IEnumerable<T>
{
    private readonly T[] array;

    public ReadOnlyArray(T[] a_array)
    {
        array = a_array;
    }

    // read-only because no `set'
    public T this[int i]
    { get { return array[i]; } }

    public int Length
    { get { return array.Length; } }

    /* 
       You can comment this method out if you don't implement IEnumerable<T>.
       Casting array.GetEnumerator to IEnumerator<T> will not work.
    */
    public IEnumerator<T> GetEnumerator()
    {
        foreach(T el in array)
        {
            yield return el;
        }
    }

    /* 
       If you don't implement any interface, change this to:
       public IEnumerator GetEnumerator()

       Or you can implement only IEnumerable (rather than IEnerable<T>)
       and keep "IEnumerator IEnumerable.GetEnumerator()"
    */
    IEnumerator IEnumerable.GetEnumerator()
    {
        return array.GetEnumerator();
    }
}
于 2009-06-04T21:51:47.903 に答える
0

配列は、順序付けられていないアイテムのセットを反復処理するための高速な方法です。

それがあなたがする必要があるすべてであるならば、ただ配列を。として返すだけIEnumerableです。 IEnumerableを自分で実装しないでください。配列はすでに実装しています。

それはあなたの3つの目標すべてを満たすはずです。

public class SomeClass
{ 
    private T[] myArray; // T could be any type

    public IEnumerable<T> MyReadOnlyArray { get { return myArray; } }
}
于 2009-06-04T22:16:23.487 に答える