12

OK、List<> には、ReadOnlyCollection を提供する AsReadOnly() が含まれています。必要なのは、IList タイプのフィールドと、このリストの ReadOnlyCollection を返すプロパティを持つことです。

クラスの例:

class Test
{
   private IList<Abc> list;

   public AddToList(Abc someItem) { /* adds inside the list */... }

   public ReadOnlyCollection<Abc> List { get { return ??? } } // <- no "set" here!
}

シナリオは次のとおりです。項目がリストに追加されるときに、クラス内にいくつかのカスタム ロジックが必要であり、list.Add( someItem)。問題は、IList インターフェイスを必要とするNHibernateを使用しているため、IListで AsReadOnly() をキャスト/呼び出しできないことです (このメソッドは含まれていません)。

この状況を解決するには、どのような方法をお勧めしますか? NHibernate が何らかの方法で必要なコレクションを設定する方法が必要なだけですが、ユーザーを制限する必要もあります。

4

5 に答える 5

30

エミュレートするだけですAsReadOnly()

public ReadOnlyCollection<Abc> List
{
    get { return new ReadOnlyCollection<Abc>(list); }
}

更新:
これは のコピーを作成しませんlistReadOnlyCollectionデータをコピーせず、提供されたリストで直接動作します。ドキュメントを参照してください:

読み取り専用のコレクションは、コレクションの変更を防止するラッパーを持つコレクションです。したがって、基になるコレクションに変更が加えられると、読み取り専用コレクションにそれらの変更が反映されます。
このコンストラクターは O(1) 操作です。

于 2011-08-29T08:10:23.380 に答える
7

試す

return new ReadOnlyCollection<Abc> (list);
于 2011-08-29T08:09:29.180 に答える
1

また、読み取り専用のイテレータを返しIEnumerable<Abc>、要素を追加および削除するためのメソッドを提供することもできます。

于 2011-08-29T11:57:41.597 に答える
1

私の意見では、これを行う最善の方法は、Jon Skeet によって提案されIEnumerable<Abc>た方法を使用して戻ることです。

public IEnumerable<Abc> Abcs {
    get { return list.Skip(0); }
}

IEnumerable<T>消費者が後ろにキャストすることを心配していない場合は、IList<T>単に戻ることができますIEnumerable<T>.

ReadOnlyCollection<T>にはいくつかの深刻な欠陥があります。主な欠陥は実装されているIList<T>ため、Add メソッドと Remove メソッドがあります。これは、コンシューマが ReadOnly プロパティのチェックを怠ると、実行時エラーにつながる可能性があります。使用しないことを強くお勧めします。

于 2011-08-29T12:43:37.197 に答える
1

次の方法を使用して、

public class Test
    {

        private IList<SubTest>      _subTests;


        public virtual void AddSubTest(SubTest SubTest)
        {
            if (_subTests == null)
                _subTests = new List<SubTest>();

            _subTests.Add(SubTest);

            return this;
        }


        public virtual IReadOnlyList<SubTest> SubTests
        {
            get
            {
                if (_subTests == null)
                    _subTests = new List<SubTest>();

                return _subTests.AsReadOnly();
            }
        }




        public void RemoveSubTest( SubTest SubTest )
        {
            if( _subTests == null ) 
                return;

            _subTests.Remove( SubTest );            
        }

    }

次のマッピングを使用すると、読み取り専用リストであるプロパティではなくフィールドに値が設定されます

<bag 
      name="SubTests" table="SubTest" lazy="true" access="field.camelcase-underscore"
      optimistic-lock="false"
      >
      <key column ="TestID" />
      <many-to-many class="SubTest, Domain" column="SubTestID" />
    </bag>
于 2011-08-29T08:14:36.917 に答える