へのアクセスを制御する内部のコレクションのc#-パターン必要
-
02-07-2019 - |
質問
このようなハードに分けてどうぞよろしくお願いいたし英語で十分:
私はクラス"A"を維持すべきリストの対象クラス"B"のような民間のリストに消費者のクラスの"A"は追加することができる項目の一覧です。後の項目がリストに追加され、消費者はできない変更し、みだらできない怒りのリスト自体の追加と削除ができます。ができる列挙の項目のリストを取得しその値には使用できません。あるパターンです。ついてはどのように捉えている。
場合には問題はないが、ぜひ<url>までご連絡ください。
解決
予防編集のリストまたはその項目において 不変なので, るまでに返さないといけないの新しいインスタンスを要素毎ます。
見Eric Lippertの優れたシリーズの"不変クライアントまで、フルのC#": http://blogs.msdn.com/ericlippert/archive/tags/Immutability/C_2300_/default.aspx いスクロール減少)
他のヒント
なんと、もしく答えがここに単純な問題です。
シートベルト List<T>
してい public void AddItem(T item)
の方法-いつ決まりましたが止まで停止作業。だが例外をスローしただけなので失敗黙々と.によって異なりますかというのがあります。
してい public T[] GetItems()
方法とは return _theList.ToArray()
として多くのこれらの回答が、多くの方法があり、収集そのものは不変です。
することができ努力委員会の不変です。一つの可能性がありファサード/代理人(しまいまして申し訳ありませんが簡潔):
class B
{
public B(int data)
{
this.data = data;
}
public int data
{
get { return privateData; }
set { privateData = value; }
}
private int privateData;
}
class ProxyB
{
public ProxyB(B b)
{
actual = b;
}
public int data
{
get { return actual.data; }
}
private B actual;
}
class A : IEnumerable<ProxyB>
{
private List<B> bList = new List<B>();
class ProxyEnumerator : IEnumerator<ProxyB>
{
private IEnumerator<B> b_enum;
public ProxyEnumerator(IEnumerator<B> benum)
{
b_enum = benum;
}
public bool MoveNext()
{
return b_enum.MoveNext();
}
public ProxyB Current
{
get { return new ProxyB(b_enum.Current); }
}
Object IEnumerator.Current
{
get { return this.Current; }
}
public void Reset()
{
b_enum.Reset();
}
public void Dispose()
{
b_enum.Dispose();
}
}
public void AddB(B b) { bList.Add(b); }
public IEnumerator<ProxyB> GetEnumerator()
{
return new ProxyEnumerator(bList.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
下の方にはこのソリューションには、呼び出しが繰り返し処理を行集ProxyB物ではなく、億物も追加されます。
編集: るためのサポートを追加しました版コンテキストを共有します。呼び出し側で追加要素内版コンテキストできaditionallyを実施する唯一の版コンテキストの寿命をのばしば。
使用封止を定義しておくことができませる政策パッケージへのアクセスの内民間。以下の例は、基本的な実装の要件:
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Collections;
class B
{
}
interface IEditable
{
void StartEdit();
void StopEdit();
}
class EditContext<T> : IDisposable where T : IEditable
{
private T parent;
public EditContext(T parent)
{
parent.StartEdit();
this.parent = parent;
}
public void Dispose()
{
this.parent.StopEdit();
}
}
class A : IEnumerable<B>, IEditable
{
private List<B> _myList = new List<B>();
private bool editable;
public void Add(B o)
{
if (!editable)
{
throw new NotSupportedException();
}
_myList.Add(o);
}
public EditContext<A> ForEdition()
{
return new EditContext<A>(this);
}
public IEnumerator<B> GetEnumerator()
{
return _myList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public void StartEdit()
{
this.editable = true;
}
public void StopEdit()
{
this.editable = false;
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
using (EditContext<A> edit = a.ForEdition())
{
a.Add(new B());
a.Add(new B());
}
foreach (B o in a)
{
Console.WriteLine(o.GetType().ToString());
}
a.Add(new B());
Console.ReadLine();
}
}
}
基本的には避けたいという思いがって非常に良い流れだったと思い参考文献には、クラスBます。だからこそなのです。
と思うことができるのToArray()メソッドのリストオブジェクトです。を作成する必要がありますの深いコピーのリストを防ぎたい場合に変化します。
一般的には:ものではないに意義があるのないコピーを実施良い行動のときものです。
public class MyList<T> : IEnumerable<T>{
public MyList(IEnumerable<T> source){
data.AddRange(source);
}
public IEnumerator<T> GetEnumerator(){
return data.Enumerator();
}
private List<T> data = new List<T>();
}
の下振れは、消費者の変更ができる項目での調査員ソリューションはdeepcopyのリスト<T>.
できるということを知らないかも必要なのはBインスタンス自体を不変なので一度リストに追加されます。をお楽しみいただけますtrickこちらを読み込み専用インタフェースB、この一覧です。
internal class B : IB
{
private string someData;
public string SomeData
{
get { return someData; }
set { someData = value; }
}
}
public interface IB
{
string SomeData { get; }
}
最も簡単なるんで返す 読み取り専用版 基本と収集の場合の編集は使用できなくなります。
public IList ListOfB
{
get
{
if (_readOnlyMode)
return listOfB.AsReadOnly(); // also use ArrayList.ReadOnly(listOfB);
else
return listOfB;
}
}
個人的にも、製品の保証や修理に関しましては、配下のリストをクライアントを持つ大手企業での提供方法の追加、削除、およびターゲットを絞り、B場合がございます。