web-dev-qa-db-ja.com

C#の「読み取り専用」プロパティアクセサー

私は次のクラスを持っています:

class SampleClass
{
   private ArrayList mMyList;

   SampleClass()
   {
       // Initialize mMyList
   }

   public ArrayList MyList
   {
       get { return mMyList;}
   }
}

ユーザーがmMyListを取得できるようにしたいので、プロパティを介して「get」を公開しましたが、オブジェクトに加えた変更(MyList.Add(new Class());)でオブジェクトを変更したくありません。私のクラスに戻ります。

私はオブジェクトのコピーを返すことができると思いますが、それは遅いかもしれません、そして私はユーザーにからの戻り値を変更することができると期待すべきではないことをユーザーに通知するコンパイル時エラーを提供する方法を探していますプロパティ。

これは可能ですか?

19
cjserio

ArrayListを使用すると、BCLに読み取り専用の非ジェネリックコレクションクラスがないため、かなり制限されます。迅速で汚い解決策は、IEnumerableのタイプを返すことです。

   public IEnumerable MyList
   {
       get { return mMyList;}
   }

これは実際には誰かがArrayListにキャストするのを妨げることはありませんが、デフォルトでは編集も許可されません

ArrayList.ReadOnlyを呼び出すことにより、効果的に読み取り専用リストを返すことができます。ただし、戻り値の型はArrayListであるため、ユーザーは.Addを使用してコンパイルできますが、ランタイムエラーが発生します。

25
JaredPar

ArrayList.ReadOnly() メソッドを使用して、リストの読み取り専用ラッパーを作成して返します。リストをコピーするのではなく、単に読み取り専用のラッパーを作成します。コンパイル時のチェックを取得するには、@ Jaredが提案するように、読み取り専用ラッパーをIEnumerableとして返すことをお勧めします。

public IEnumerable MyList
{
     get { return ArrayList.ReadOnly(mMyList); }
}

読み取り専用のコレクションは、コレクションの変更を防ぐラッパーを備えたコレクションです。基になるコレクションに変更が加えられた場合、読み取り専用コレクションはそれらの変更を反映します。

このメソッドはO(1)操作です。

参照

19
tvanfosson

JaredParの答えを拡張するだけです。彼が言ったように、実際のバッキングフィールドを返すことは完全に安全ではありません。ユーザーはまだIEnumerableArrayListに動的にキャストできるからです。

元のリストに変更が加えられていないことを確認するために、次のように記述します。

public IEnumerable MyList
{
    get
    {
         foreach (object o in mMyList)
             yield return o;
    }
}

それからまた、私はおそらく一般的なリスト(IEnumerable<T>)完全にタイプセーフであること。

9
Tom Lokhorst
4
Svish

ReadOnlyCollectionを使用します。

return new ReadOnlyCollection<object>(mMyList)

ReadOnlyCollectionをフィールドにすることもでき、基になるリストの変更が自動的に反映されます。これが最も効率的なソリューションです。

MMyListに含まれるオブジェクトのタイプが1つだけであることがわかっている場合(たとえば、DateTimesしか含まれていない場合)、タイプの安全性を高めるために_ReadOnlyCollection<DateTime>_(またはその他のタイプ)を返すことができます。 C#3を使用している場合は、次のように簡単に記述できます。

return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())

ただし、これは基になるリストで自動的に更新されず、効率も低下します(リスト全体がコピーされます)。最良のオプションは、mMyListを汎用の_List<T>_(たとえば、_List<DateTime>_)にすることです。

4
SLaks

戻り値を読み取り専用コレクションでラップする必要があります。

1
Mehrdad Afshari

.NETv2.0から利用可能

    public ArrayList MyList { get; private set; }
0
wloescher