4

これらのどれが最もクリーンまたは使用するのに最適であると考えられるのか、そしてその理由は何か疑問に思っています。

1つは乗客のリストを公開し、ユーザーが追加や削除などを行えるようにします。もう1つはリストを非表示にし、ユーザーが乗客を列挙して特別な方法で追加することのみを許可します。

例1

class Bus
{
    public IEnumerable<Person> Passengers { get { return passengers; } }
    private List<Passengers> passengers;

    public Bus()
    {
        passengers = new List<Passenger>();
    }

    public void AddPassenger(Passenger passenger)
    {
        passengers.Add(passenger);
    }
}

var bus = new Bus1();
bus.AddPassenger(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

例2

class Bus
{
    public List<Person> Passengers { get; private set; }

    public Bus()
    {
        Passengers = new List<Passenger>();
    }
}

var bus = new Bus();
bus.Passengers.Add(new Passenger());
foreach(var passenger in bus.Passengers)
    Console.WriteLine(passenger);

私が言う最初のクラスはよりよくカプセル化されています。そして、この正確なケースでは、それがより良いアプローチかもしれません(おそらくバスに残っているスペースがあることを確認する必要があるためなど)。しかし、2番目のクラスも役立つ場合があると思いますか?クラスがリストを持っている限り、そのリストがどうなるかをクラスが本当に気にしない場合のように。どう思いますか?

4

5 に答える 5

6

例 1 では、コレクションを変更することができます。

次の点を考慮してください。

var passengers = (List<Passenger>)bus.Passengers;

// Now I have control of the list!
passengers.Add(...);
passengers.Remove(...);

これを修正するには、次のようなことを検討してください。

class Bus
{
  private List<Passenger> passengers;

  // Never expose the original collection
  public IEnumerable<Passenger> Passengers
  {
     get { return passengers.Select(p => p); }  
  }

  // Or expose the original collection as read only
  public ReadOnlyCollection<Passenger> ReadOnlyPassengers
  {
     get { return passengers.AsReadOnly(); }
  }

  public void AddPassenger(Passenger passenger)
  {
     passengers.Add(passenger);
  }
 }
于 2009-08-05T08:40:32.470 に答える
0

オプション 2 は最も単純ですが、他のクラスがコレクションに要素を追加/削除できるため、危険な場合があります。

良いヒューリスティックは、ラッパー メソッドが何をするかを検討することだと思います。AddPassenger (または Remove など) メソッドが単にコレクションへの呼び出しを中継している場合は、より単純なバージョンを使用します。要素を挿入するにチェックする必要がある場合、オプション 1 は基本的に避けられません。挿入/削除された要素を追跡する必要がある場合は、どちらの方法でもかまいません。オプション 2 では、コレクションにイベントを登録して通知を受け取る必要があり、オプション 1 では、使用するリストのすべての操作のラッパーを作成する必要があります (たとえば、挿入と追加が必要な場合)。場合によります。

于 2009-08-05T08:55:38.617 に答える
0

それはすべてあなたの状況にかかっていると思います。より厳密な制御を追加するビジネス上の理由がない限り、通常はオプション 2 を選択します。

于 2009-08-05T08:40:56.370 に答える
0

ほとんどの場合、内部クラスがコレクションへの変更に応答できるように、基になる型が拡張可能であり、および/または何らかの形式の onAdded/onRemoved イベントを公開していれば、例 2 は受け入れられると考えます。

この場合、何かが追加されたかどうかをクラスが知る方法がないため、List<T> は適していません。Collection<T> クラスには、オーバーライドできる複数の仮想メンバー (Insert、Remove、Set、Clear) があり、ラッピング クラスに通知するためにイベント トリガーが追加されるため、代わりに Collection を使用する必要があります。

(クラスのユーザーは、親クラスが知らないうちにリスト/コレクション内のアイテムを変更できることにも注意する必要があります。そのため、明らかに不変でない限り、アイテムが変更されていないことに依存しないようにしてください。 - または、必要に応じて onChanged スタイルのイベントを提供できます。)

于 2009-08-05T08:29:34.210 に答える
0

FxCop を介してそれぞれの例を実行すると、公開のリスクについてのヒントが得られるはずです。List<T>

于 2009-08-05T08:37:36.953 に答える