문제

나는있다 ICollection<T> ~라고 불리는 foos 내 수업에서 읽기 전용으로 드러내고 싶습니다 (참조 이 질문). 인터페이스가 속성을 정의합니다 .IsReadOnly, 적절한 것 같다 ... 내 질문은 이것이다 : 어떻게 수업 소비자에게 foos 읽기 전용입니까?

나는 쿼리를 기억하는 그들에게 의존하고 싶지 않다 .IsReadOnly 다음과 같은 구현되지 않은 방법을 시도하기 전에 .Add(). 이상적으로는 노출하고 싶습니다 foos A로 ReadOnlyCollection<T>, 그러나 구현되지 않습니다 IList<T>. 노출해야합니다 foo 예를 들어,이라는 메소드를 통해 GetReadOnlyFooCollection 재산을 통한 대신? 그렇다면 이것은 ReadOnlyCollection<T>?

이것은 C# 2.0이므로 확장 방법과 같은 연장 방법 ToList() 사용할 수 없습니다 ...

도움이 되었습니까?

해결책

나는 ienumerable의 귀환에 정착 한 것 같습니다 물체가 복제 된 상태에서.

public IEnumerable<Foose> GetFooseList() {
   foreach(var foos in Collection) {
     yield return foos.Clone();
   }
}
  • foos에 복제 방법이 필요합니다.

이것은 컬렉션을 변경할 수 없습니다. 다른 게시물의 링크에 언급 된대로 내부의 객체를 변경할 수 있기 때문에 ReadonLyCollection은 "누출"입니다.

다른 팁

"foos"를 이와 같이 readonlycollection으로 만들 수 있습니다.

ReadOnlyCollection<T> readOnlyCollection = foos.ToList<T>().AsReadOnly();

그런 다음 수업의 재산으로 노출 될 수 있습니다.

편집하다:

    class FooContainer
    {
        private ICollection<Foo> foos;
        public ReadOnlyCollection<Foo> ReadOnlyFoos { get { return foos.ToList<Foo>().AsReadOnly();} }

    }

참고 : 일단 readonlyfoos 컬렉션을 받으면 더 이상 Foos Icollection과 "동기화"되지 않음을 기억해야합니다. 참조 참조 한 스레드.

질문이 작성된 이후 .NET 4.0은 IReadOnlyCollection<T> 상호 작용; 아마도 그것을 선언 된 반환 유형으로 사용하는 것이 좋을 것입니다.

그러나 그것은 어떤 유형의 의지에 대한 질문을 열어줍니다. 사례 돌려 주다. 한 가지 방법은 원래 컬렉션의 모든 항목을 복제하는 것입니다. 다른 하나는 항상 읽기 전용 래퍼를 반환하는 것입니다. 세 번째는 원래 컬렉션을 구현하는 경우 원래 컬렉션을 반환하는 것입니다. IReadOnlyCollection<T>. 각 접근법은 특정 상황에서 가장 좋은 방법이지만 다른 접근법은 다른 방법으로 이상적이지 않을 것입니다. 불행히도, Microsoft는 질문에 두 가지 매우 중요한 질문을 할 수있는 표준 수단을 제공하지 않습니다.

  1. 당신은 항상 그리고 영원히 당신이 지금하는 것과 같은 품목을 포함하겠다고 약속합니까?

  2. 내용을 수정하지 않아야하는 코드에 직접 노출 될 수 있습니까?

어떤 스타일의 래핑 스타일은 클라이언트 코드가받는 것과 관련이있는 것에 따라 다릅니다. 피해야 할 몇 가지 시나리오 :

  1. 클라이언트가 불변으로 인식 할 수있는 유형의 객체가 제공되었지만 직접 반환되지 않고 클라이언트가 불변으로 인식하지 못하는 유형을 사용하여 복제됩니다. 결과적으로 클라이언트는 컬렉션을 다시 복제해야합니다.

  2. 개체는 클라이언트가 불변으로 인식 할 수있는 유형의 개체를 제공했지만 반품되기 전에 클라이언트가 컬렉션이 불변인지 아닌지 알 수 없어서 복제되도록 강요 할 수없는 방식으로 포장됩니다.

  3. 돌연변이되지 않아야하는 돌연변이 유형의 객체는 클라이언트에 의해 제공됩니다 (읽기 전용 인터페이스로 캐스트). 그런 다음 다른 클라이언트에 직접 노출되어 변이 가능한 유형이라는 것을 결정하고 수정합니다.

  4. 변한 컬렉션에 대한 참조가 수신되고 불변의 객체가 필요한 클라이언트에게 반환되기 전에 읽기 전용 래퍼에 캡슐화됩니다. 이 컬렉션을 반환 한 방법은이 컬렉션이 불변이라고 약속했으며, 따라서 고객은 자체 방어 사본을 작성하는 것을 거부했습니다. 그런 다음 클라이언트는 컬렉션이 변경 될 가능성에 대해 준비가되지 않습니다.

실제로 "안전한"행동 과정은 없습니다. 객체는 일부 고객으로부터받는 컬렉션으로 취할 수 있으며 다른 클라이언트에 노출되어야합니다. 항상 모든 것을 복제하는 것은 많은 상황에서 가장 안전한 행동 과정이지만, 전혀 복제 할 필요가없는 컬렉션이 수백 ~ 수천 번 복제 될 수있는 상황에서 쉽게 발생할 수 있습니다. 수신 된 참조를 반환하는 것이 종종 가장 효율적인 접근법 일 수 있지만 의미 적으로 위험 할 수도 있습니다.

Microsoft가 컬렉션이 위의 질문을 요청할 수있는 표준 수단을 추가하거나, 더 나은 아직, 현재 상태의 불변의 스냅 샷을 만들어 달라는 요청을 받기를 바랍니다. 불변의 컬렉션은 현재 상태의 불변의 불변의 스냅 샷을 매우 저렴하게 반환 할 수 있으며 (그냥 반환), 일부 변이 가능한 컬렉션 유형조차도 전체 열거 비용보다 훨씬 낮은 비용으로 불변의 스냅 샷을 반환 할 수 있습니다 (예 : List<T> 2로 뒷받침 될 수 있습니다 T[][] 그 중 하나는 256 개 항목의 공유 가능한 불변 배열에 대한 참조를 보유하고 있으며, 그 중 하나는 256 개 항목의 샤워 할 수없는 돌연변이 어레이에 대한 참조를 보유하고 있습니다. 목록의 스냅 샷을 만들려면 마지막 스냅 샷 이후 수정 된 항목이 포함 된 내부 배열 만 복제해야합니다. 전체 목록을 복제하는 것보다 훨씬 저렴합니다. 불행히도 표준 "불변의 스냅 샷 만들기"인터페이스가 없기 때문에 [참고 ICloneable 돌연변이 목록의 클론은 변이 가능하기 때문에 계산되지 않습니다. 읽기 전용 래퍼에서 변한 클론을 캡슐화하여 불변의 스냅 샷을 만들 수 있지만, 클로닝 가능한 것들에만 효과가 있으며 클로닝 할 수없는 유형조차도 여전히 "Mutable Snapshot"기능을 지원해야합니다.

내 권장 사항은 ReadonLyCollection을 사용하는 것이 좋습니다u003CT> 시나리오의 경우 직접. 이렇게하면 사용량이 호출 사용자에게 명시 적입니다.

일반적으로 적절한 인터페이스를 사용하는 것이 좋습니다. 그러나 .NET 프레임 워크에 현재 적합한 IreadonLyCollection이 없다는 점을 감안할 때 ReadOnlyCollection 유형을 사용해야합니다.

또한 ReadonLyCollection을 사용할 때는 실제로 읽기 전용이 아니기 때문에 알고 있어야합니다. 불변성과 ReadonLycollection

때로는 단위 테스트 중에 컬렉션을 조롱하고 싶기 때문에 인터페이스를 사용하고 싶을 수도 있습니다. 내 참조하십시오 블로그 항목 어댑터를 사용하여 readonycollection에 자신의 인터페이스를 추가합니다.

나는 일반적으로 반환합니다 IEnumerable<T>.

컬렉션을 읽기로 만들면 Add, Remove 그리고 Clear 더 이상 작동하지 않음) 컬렉션이 열거 할 수없는 것이 아니라 Count 그리고 Contains, 나는 믿는다.

학급의 소비자가 실제로 컬렉션에있는 것처럼 요소를 처리해야한다면 IEnumerable 에게 List<T>의 생성자.

t []를 반환합니다.

private ICollection<T> items;

public T[] Items
{
    get { return new List<T>(items).ToArray(); }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top