2010-12-15 3 views
5

IList을 구현하는 읽기 전용 컬렉션을위한 추상 기본 클래스를 작성하려고합니다. 이러한 기본 클래스는 NotSupportedException을 던지기 위해 set-indexer를 구현해야하지만 get-indexer는 추상으로 남겨 두어야합니다. C#에서 그런 상황이 가능합니까? 여기에 지금까지이 작업은 다음과 같습니다C에서 콘크리트 세터가있는 추상 게터 #

public abstract class ReadOnlyList : IList { 

    public bool IsReadOnly { get { return true; } } 

    public object this[int index] { 
     get { 
      // there is nothing to put here! Ideally it would be left abstract. 
      throw new NotImplementedException(); 
     } 
     set { 
      throw new NotSupportedException("The collection is read-only."); 
     } 
    } 

    // other members of IList ... 
} 

이상적으로 ReadOnlyList은 세터를 구현하지만 게터 초록을 떠날 수있을 것입니다. 이것을 허용하는 구문이 있습니까?

+5

이 단지 운동하지, 당신은 프레임 워크 –

+0

덕분에 ReadOnlyCollection 있다; 필자는 보통 ReadOnlyCollection 을 사용합니다.이 경우 IList 의 사용자 지정 구현이 필요합니다. 나는 질문을하기 위해 필요한 최소한의 시나리오를 간소화하는 경향이있다. –

답변

8

대표에게 당신이 그 다음으로 추상 또는 가상이 원하는 동작에 따라 표시 할 수 있습니다 보호 회원들에게 작업을 필요 없어요. 이런 식으로 뭔가를 시도 : 경우

// implementor MUST override 
protected abstract object IndexerGet(int index); 

// implementor can override if he wants.. 
protected virtual void IndexerSet(int index, object value) 
{ 
    throw new NotSupportedException("The collection is read-only."); 
} 

public object this[int index] { 
    get { 
    return IndexerGet(index); 
    } 
    set { 
    IndexerSet(index, value); 
    } 
} 
+0

IndexerSet은 가상 *이 아닐 것입니다. 실제로는 setter 자체에'NotSupportedException'을 던지면됩니다. –

+1

감사합니다. m0sa. setter를 구현하고 파생 클래스를 강제로 구현하여 getter를 구현하는 목표를 달성하는 유일한 해결책이기 때문에이를 대답으로 받아 들였습니다. 말할 필요도없이 지금까지 컴파일 할 수있는 유일한 대답입니다! –

-1

왜 setter를 사용하고 싶습니까? setter가 없으면 읽기 전용 속성을 나타냅니다.

EDIT : jgauffin은 setter가 IList에서 온 것이라고 지적했습니다. 따라서 두 가지 옵션이있을 수 있습니다.

  1. 개인적으로 IList를 구현하고 인덱서에 대해 공개 초록 getter를 제공합니다 (두 개의 인덱서를 사용할 수 있으면 100 % 확실하지는 않습니다).
  2. Indexer getter는 GetItem과 같은 추상 메서드를 호출합니다.
+0

'IList'가 인덱서를 정의하기 때문에. – jgauffin

+0

인터페이스에서 [필수] (http://msdn.microsoft.com/en-us/library/system.collections.ilist.item.aspx)입니다. –

0

세터를 비공개로 설정하지 않으시겠습니까?

public abstract class ReadOnlyList : IList 
    { 

     public bool IsReadOnly { get { return true; } } 

     public object this[int index] 
     { 
      get 
      { 
       // there is nothing to put here! Ideally it would be left abstract. 
       throw new NotImplementedException(); 
      } 
      private set 
      { 
       // your private implementation 
      } 
     } 

     // other members of IList ... 
    } 
+4

인덱서가 'IList'에 정의되어 있기 때문에 컴파일 오류가 발생합니다. – jgauffin

+2

인터페이스가 공개되어야하며 getter 추상을 유지하려는 욕구를 충족시키지 못했습니다. –

+1

mm 맞아, 그 중 하나에 대해 생각하지 않았다 –

2

아니요, 회원 초록과 다른 속성으로 구성된 속성을 가질 수 없습니다. 내가 할 수있는 것은 전체 속성을 추상으로 설정하고 상속인이 원하는대로 수행하도록 다시 정의하는 것입니다.

+0

SoMoS; 질문에 대답 한 대답으로 m0sa의 대답을 받아 들였지만 나는 여분의 수준의 간접 지정을 피하기 위해 궁극적으로 제안한 접근 방식을 사용했습니다. –

+0

아무 문제가없는 남자, 어쨌든 mOsa 대답도 좋은 것입니다. –

0

아니요. 그렇게 할 수있는 방법을 찾으면 Liskov Substitution Principle을 정말로 깨뜨립니다.

여기 LSP에 대한 자세한 읽기 : Can you explain Liskov Substitution Principle with a good C# example?

+0

어떻게 LSP가 깨지나요?구상 서브 클래스는 구체적 getter 구현을 제공해야합니다. 그렇게하는 경우 해당 하위 클래스는 (다른 문제가 없을 경우) 잘 동작하는 IList (허용됨) (http://msdn.microsoft.com/en-us/library/system.collections.ilist. isreadonly.aspx)를 읽기 전용으로 설정하십시오. –

+1

'IList'를 사용하는 사람은 목록에서 항목을 가져오고 설정할 수 있기를 기대합니다. .Net 프레임 워크의'ReadOnlyCollection'도 LSP에 위배됩니다. 왜냐하면 그 요구 사항을 충족시키지 못하기 때문입니다. – jgauffin

+0

아니요. 내 링크를 확인한 경우 'IList'가 명시 적으로 읽기 전용으로 설계되어 있음을 알 수 있습니다. 그것이 바로 'IList.IsReadOnly'의 특징입니다. 따라서 읽기 전용 하위 클래스는 쉽게 "대체"할 수 있습니다. –

0

당신이 다음 읽기 전용 컬렉션을하고 싶다면 왜 IList 구현을?

대신 IEnumerable을 구현해야합니다.

+1

IList는 명시 적으로 허용된다. (http : // msdn Microsoft.com/ko-kr/library/system.collections.ilist.isreadonly.aspx)을 읽기 전용으로 설정하십시오. 'IEnumerable'은 랜덤 액세스를 제공하지 않습니다. –

+0

이것이 'ReadOnlyCollection <>'솔루션만큼 완벽하지는 않지만 실제로는 수시로 충분하며 더욱 단순한 API가된다는 장점이 있습니다. 바로 그게 중요한 것입니까? IEnumerable이 불충분 한 경우에만 ReadOnlyCollection을 지원할 것입니다. –

+0

또한, 'IEnumerable'플레이어는 타입 시스템에 더 좋았습니다 : 저는 흔히 컬렉션을 뒤섞고 정렬하는 방법을 사용합니다. 이것들은 ILists에서 작동합니다. 읽기 전용 ILists는 런타임에 실패하지만 IEnumerable을 전달하면 컴파일 타임에 실패합니다. 그것은 더 좋은 행동입니다. –

-2

당신은 세터

public abstract object this[int index] { get; } 
+0

같은 대답을했던 다른 답변도 읽어보십시오. –

관련 문제