문제

이 중 어느 것이 사용하기에 가장 깨끗하거나 가장 좋은 것으로 간주되며 그 이유가 무엇인지 궁금합니다.

그 중 하나는 사용자가 승객을 추가하고 제거할 수 있는 승객 목록을 노출합니다.다른 하나는 목록을 숨기고 사용자가 목록을 열거하고 특별한 방법을 사용하여 추가하도록 합니다.

실시예 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학년도 유용하게 쓸 수 있는 경우가 있지 않을까요?마치 클래스가 목록이 있는 한 그 목록에 무슨 일이 일어나는지 전혀 신경 쓰지 않는 것처럼 말이죠.어떻게 생각하나요?

도움이 되었습니까?

해결책

예를 들어, 컬렉션을 돌연변이 할 수 있습니다.

다음을 고려하세요:

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);
  }
 }

다른 팁

대부분의 경우 내부 클래스가 컬렉션에 대한 모든 변경 사항에 응답할 수 있도록 기본 유형이 확장 가능하고 onAdded/onRemoved 이벤트 형식을 노출하는 경우 예제 2를 허용할 수 있다고 생각합니다.

이 경우 List<T>는 클래스가 무언가 추가되었는지 알 수 있는 방법이 없기 때문에 적합하지 않습니다.대신 Collection<T> 클래스에는 재정의할 수 있고 래핑 클래스에 알리기 위해 이벤트 트리거를 추가할 수 있는 여러 가상 멤버(Insert,Remove,Set,Clear)가 있으므로 Collection을 사용해야 합니다.

(또한 클래스 사용자가 상위 클래스가 알지 못하는 사이에 목록/컬렉션의 항목을 수정할 수 있다는 점을 알아야 합니다. 따라서 항목이 변경되지 않을 것이라고 확신하지 마십시오. 명백히 변경할 수 없는 경우는 제외됩니다. - 또는 필요한 경우 onChanged 스타일 이벤트를 제공할 수 있습니다.)

FXCOP를 통해 각각의 예제를 실행하면 노출 위험에 대한 힌트를 줄 수 있습니다. List<T>

나는 그것이 당신의 상황에 달려 있다고 말할 것입니다. 나는 보통 옵션 2를 위해 가장 간단하기 때문에 갈 것입니다. ~하지 않는 한 당신은 그것에 더 큰 컨트롤을 추가 할 사업적인 이유가 있습니다.

옵션 2가 가장 간단하지만 다른 클래스가 컬렉션에 요소를 추가/제거 할 수있게 해주므로 위험 할 수 있습니다.

좋은 휴리스틱은 래퍼 방법이 무엇을하는지 고려하는 것입니다. AddPassenger (또는 제거 또는 기타) 메소드가 단순히 컬렉션에 호출을 전달하는 경우 더 간단한 버전으로 이동합니다. 요소를 확인 해야하는 경우 ~ 전에 그것들을 삽입하면 옵션 1은 기본적으로 피할 수 없습니다. 삽입/삭제 된 요소를 추적 해야하는 경우 어느 쪽이든 갈 수 있습니다. 옵션 2를 사용하면 알림을 얻으려면 컬렉션에 이벤트를 등록해야하며 옵션 1을 사용하면 사용하려는 목록의 모든 작업에 대한 랩퍼를 만들어야합니다 (예 : 삽입 및 추가를 원하는 경우). 때에 따라 다르지.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top