2009-03-06 4 views
19

나는 다음 클래스가 있습니다C#에서 속성 접근 자 "읽기 전용"

class SampleClass 
{ 
    private ArrayList mMyList; 

    SampleClass() 
    { 
     // Initialize mMyList 
    } 

    public ArrayList MyList 
    { 
     get { return mMyList;} 
    } 
} 

I 사용자가 내가 노출 왜 mMyList를 얻을 수 있도록하려면를하지만 내가하지 않는 속성을 통해 "GET" (MyList.Add (new Class());) 객체에 대한 변경 사항을 내 클래스로 되돌리려 고합니다.

개체의 복사본을 반환 할 수 있지만 느려질 수 있으며 컴파일 타임 오류를 제공 할 것이라고 사용자에게 알립니다. 속성에서 반환 된 값.

이것이 가능합니까?

+0

관련 질문 mMyList입니다/질문/681287/방법 - 투 - 메이크업 - 읽기 전용 A-참조 형 재산권 –

+2

합니까'목록 이의 .NET 4.5 변화 ReadOnlyCollection '? http://www.infoq.com/news/2011/10/ReadOnly-WInRT/ –

답변

25

ArrayList를 사용하면 BCL에 읽기 전용 비 제너릭 컬렉션 클래스가 없으므로 상당히 제한적입니다. 빠르고 쉬운 해결책은 IEnumerable 유형을 반환하는 것입니다.

public IEnumerable MyList 
    { 
     get { return mMyList;} 
    } 

실제로 위해 ArrayList 캐스팅에서 누군가를 방지하지 않습니다하지만 당신은 ArrayList.ReadOnly를 호출하여 효과적으로 읽기 전용 목록을 반환 할 수 있습니다 기본 중 하나

에 의해 편집을 허용하지 않습니다. 그러나 반환 형식은 ArrayList이므로 사용자는 .Add를 사용하여 컴파일 할 수는 있지만 런타임 오류가 발생합니다.

1

반환 값은 읽기 전용 모음으로 묶어야합니다.

19

ArrayList.ReadOnly() 메서드를 사용하여 목록 주위에 읽기 전용 래퍼를 구성하고 반환하십시오. 목록을 복사하지 않고 단순히 읽기 전용 래퍼를 만듭니다. 컴파일 타임 검사를하기 위해 아마도 @Jared가 제안하는 IEnumerable처럼 읽기 전용 래퍼를 반환하려고 할 것입니다.

public IEnumerable MyList 
{ 
    get { return ArrayList.ReadOnly(mMyList); } 
} 

된 컬렉션은 읽기 전용이다 단순히 컬렉션 수정 방지 래퍼 과 모음. 기본 컬렉션 컬렉션이 변경되면 읽기 전용 컬렉션에 이러한 변경 사항이 반영됩니다.

이 메서드는 O (1) 연산입니다.

또한
public sealed readonly ArrayList MyList 
    { 
     get { return mMyList;} 
    } 

하면 백업 필드와 같은 읽기 전용으로 만들기 위해 잊지 마세요 : 다음과 같이 읽기 전용 실드 (또는 NotInheritable VB.NET에서)와 같은

Reference

+2

이 솔루션은 컴파일 타임 오류가 런타임 오류로 바뀌어 야하기 때문에 반대입니다. – JaredPar

+0

-1, OP : "나는 ** 컴파일 시간을 제공 할 방법을 찾고 있어요 ** 오류"는 ReadOnlyCollection에 복사하지 않고 –

+0

- 내가 읽기 적용을 선택 - 그는 또한 그가 피하기 위해 원했다 오직 읽기 전용 인 척. 두 가지를 모두하는 것이 실제로 더 좋습니다. – tvanfosson

-3

그냥 재산을 :

private readonly ArrayList mMyList; 

그러나 mMyList의 값을 초기화하려면 생성자 a에서만 초기화해야합니다. 이 예에서 :

public SampleClass() 
{ 
    // Initialize mMyList 
    mMyList = new ArrayList(); 
} 
10

그냥 JaredPar의 대답을 확장하십시오. 사용자가 여전히 IEnumerableArrayList으로 동적으로 캐스팅 할 수 있기 때문에 실제 백업 필드를 반환하는 것은 완전히 안전하지는 않습니다.

나는 원래 목록에 아무런 변경이 이루어지지 않습니다 확인하기 위해 다음처럼 작성할 수 있습니다 :

public IEnumerable MyList 
{ 
    get 
    { 
     foreach (object o in mMyList) 
      yield return o; 
    } 
} 

그럼 다시, 나는 probabily도 완전히 안전한 입력 할 일반적인 목록 ( IEnumerable<T>)를 사용합니다.

+0

*이 말이 맞습니다. 두 번 투표 할 수 있기를 바랍니다. 루프 다음에 'yield break;'를 호출하지 않으면 어떤 문제가 발생합니까? – Jay

+0

@Jay : 루프 이후에는 명시적인 'yield break;'가 필요하지 않습니다. 이 메소드의 끝은'Enumerator'의 끝을 의미합니다 (그리고'MoveNext'는 올바르게'false'를 리턴 할 것입니다). –

+0

이 솔루션을 사용하면 사용자가 빠른 임의 액세스 및 빠른 Count와 같은 ArrayList의 기능을 잃지 않습니다? –

4

사용하십시오 ReadOnlyCollection.

return new ReadOnlyCollection<object>(mMyList).

또한 ReadOnlyCollection 필드를 만들 수 있으며 기본 목록의 변경 사항을 자동으로 반영합니다. 이것이 가장 효율적인 솔루션입니다.

mMyList에 한 유형의 개체 만 포함되어있는 경우 (예 : DateTimes 만있는 경우) 추가 형식 안전을 위해 ReadOnlyCollection<DateTime> (또는 다른 형식)을 반환 할 수 있습니다. 당신은 C# 3를 사용하는 경우, 당신은 단순히 그러나 return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())

, 이것은 자동으로 기본 목록을 업데이트하지 않습니다 쓰기, 또한 효율성이 떨어집니다 수 있습니다 (이것은 전체 목록을 복사합니다) . http://stackoverflow.com : 가장 좋은 방법은 만드는 일반적인 List<T> (예를 들어, List<DateTime>) .NET 2.0에서 사용 가능한

0

public ArrayList MyList { get; private set; } 
+0

기존 목록에 추가 기능을 계속 사용할 수 있습니다. –