2011-01-20 4 views
47

List<T>을 공개하지만 개인적으로 설정할 수 있도록하려면 어떻게해야합니까?목록 <T> 개인 설정으로 읽기 전용

이 작동하지 않습니다

public List<string> myList {readonly get; private set; } 

을 당신이 할 경우에도 :

public List<string> myList {get; private set; } 

당신은 여전히이 작업을 수행 할 수 있습니다

myList.Add("TEST"); //This should not be allowed 

을 당신이 할 수 같아요

public List<string> myList {get{ return otherList;}} 
private List<string> otherList {get;set;} 
,210

답변

87

나는 당신이 개념을 혼합하고 있다고 생각합니다.

public List<string> myList {get; private set;} 

이미 "읽기 전용"입니다. 당신은 "나는 사람들이 목록을 내용을 수정할 수 없도록하려면"에서와 같이 읽기 전용 목록을 원하는 경우 즉,이 클래스 이외의 아무것도, 그러나 List<string>

의 다른 인스턴스에 myList을 설정할 수있다, ReadOnlyCollection<string>을 노출해야합니다. 첫 번째 코드 조각에서, 다른 사람들이 목록을 조작 할 수 있습니다,하지만 당신은 무엇을 목록 변경할 수 없습니다

private List<string> actualList = new List<string>(); 
public ReadOnlyCollection<string> myList 
{ 
    get{ return actualList.AsReadOnly();} 
} 

참고 : 당신은을 통해이 작업을 수행 할 수 있습니다. 두 번째 스 니펫에서는 다른 사용자가 수정할 수없는 읽기 전용 목록을 가져옵니다.

+2

좋은 점에 원치 않는 캐스팅을 방지하려는 경우. 많은 사람들이 참조 유형 개념을 놓치고 참조를 읽기 전용으로 설정합니다. +1 –

+4

IList 으로 ReadOnlyCollection을 사용하는 것이 더 좋습니다. – Joe

+0

+1. 공용 System.Collections.ObjectModel.ReadOnlyCollection을 반환하면 컴파일 타임 검사를 제공하기 때문에 공용 속성에서 "개인 집합"을 사용하는 것보다 낫습니다. 즉, 읽기 전용 컬렉션에서 Add() 또는 RemoveAt()를 사용하면 컴파일 오류가 발생하지만 "개인 집합"은 그렇지 않습니다. – MikeTeeVee

11

당신이 원하는 경우 읽기 전용 컬렉션을 사용 ReadOnlyCollection<T>하지 List<T> :

ReadOnlyCollection<T>라는 컬렉션있다
public ReadOnlyCollection<string> MyList { get; private set; } 
4

이 - 당신이 찾고있는 무엇이다?

4

List의 AsReadOnly() 메서드를 사용하여 읽기 전용 래퍼를 반환 할 수 있습니다.

1

왜 목록을 사용하고 있습니까? 당신이 정말로 노출 할 것이는 IEnumerable처럼

public IEnumerable<string> myList { get; private set; } 

지금 클래스의 사용자가 항목을 읽을 수 있지만 목록을 chagnge 수없는 소리.

+1

결함!List <>로 캐스팅하고 값을 추가 할 수 있습니다. MyClass m = new MyClass(); 리스트 x = m.Values를리스트로 사용 ; x.Add ("test"); foreach (m.Values의 문자열 s) { Console.WriteLine (s); } –

+4

예, ** 할 수있는 일이 많습니다. 물론 myList를리스트 이외의 것으로 설정하면 코드가 손상 될 수 있습니다. 저는 대개 캡슐화를 의도적으로 무시하는 사람들에 의해 야기 된 문제에 대해 걱정하지 않습니다. – tster

+1

"캡슐화를 무시하는"사람들에 대해 걱정할 필요가 없습니다. 캡슐화는 캡슐화이며 한 유형을 다른 유형으로 변환 할 수있는 것은 캡슐화와 아무 관련이 없습니다. 당신이 그것을 할 것이라면, 바로하십시오. –

1

또한 일반 목록을 만들 수 있지만 IEnumerable을 유형의 속성을 통해 노출 될 수

private List<int> _list = new List<int>(); 

public IEnumerable<int> publicCollection{ 
    get { return _list; } 
} 
+0

페이지에 결함이 있습니다. List <>로 캐스팅하고 값을 추가 할 수 있습니다. MyClass m = new MyClass(); 리스트 x = m.Values를리스트로 사용 ; x.Add ("test"); foreach (m.Values의 문자열) {Console.WriteLine (s); } –

+1

실제로 _list.AsEnumerable()도 List에 캐스팅 할 수 있습니다. 놀랍습니다. –

+0

'IEnumerable '을'List '에 캐스팅 할 수있는 사람은 어리석은 사람입니다. –

4
private List<string> my_list; 

public ReadOnlyCollection<string> myList 
{ 
    get { return my_list.AsReadOnly(); } 
    private set { my_list = value; } 
} 
10

<>

private List<string> myList; 

public IList<string> MyList 
{ 
    get{return myList.AsReadOnly();} 
} 
3
private List<string> _items = new List<string>();   

    public ReadOnlyCollection<string> Items 

    { 

     get { return _items.AsReadOnly(); } 

     private set { _items = value } 

    } 
2
private List<string> myList; 

public string this[int i] 
{ 
    get { return myList[i]; } 
    set { myList[i] = value; } 
} 
은 IList를 구현 돌려 ReadOnlyCollection,
11

IEnumerabl을 사용하는 것을 선호합니다. 여기에 전자

private readonly List<string> _list = new List<string>(); 

public IEnumerable<string> Values // Adding is not allowed - only iteration 
{ 
    get { return _list; } 
} 
+10

이것은 결함이 있다는 점을 제외하면 좋은 접근법입니다. MyClass m = new MyClass(); 리스트 x = m.Values를리스트로 사용 ; x.Add ("test"); foreach (m.Values의 문자열) {Console.WriteLine (s); } // 이렇게하면 캐스팅만으로 값을 추가 할 수 있습니다. –

+5

글쎄, 그건 해킹 :) 당신은 또한 내부 컬렉션에 요소를 추가하는 반사를 사용할 수 있습니다. IEnumerable은 MyClass 클라이언트에서 구현을 숨 깁니다. 내가 LinkedList를 내부에서 사용하지 않고 있는지 확인 하시겠습니까? –

+3

컬렉션 유형을 찾기 위해 언제든지 반영 할 수 있으므로 항상 확신합니다. 당신이 그것을 할 것이라면, 바로하십시오. 물론 누구나 리플렉션을 사용하여 개체를 "해킹"하여 항목을 추가 할 수 있지만 그렇게 할 수는 없습니다. 적절한 기술을 연습하고 프레임 워크를 유용하게 사용하면됩니다. –

3

조금 늦게 한 가지 방법

public class MyClass 
    { 
     private List<string> _myList; 
     public ReadOnlyCollection<string> PublicReadOnlyList { get { return _myList.AsReadOnly(); } } 

     public MyClass() 
     { 
      _myList = new List<string>(); 
      _myList.Add("tesT"); 
      _myList.Add("tesT1"); 
      _myList.Add("tesT2"); 

      //(_myList.AsReadOnly() as List<string>).Add("test 5"); 
     } 

    } 
+1

음 ... 당신은 그냥 PublicReadOnlyList getter 새로운 ReadOnlyCollection (_myList) –

0

이지만, 그럼에도 불구하고 : 나는 여전히 컬렉션을 수정하기위한 모든 방법을 노출하기 때문에 ReadOnlyCollection 래퍼를 사용하여 좋아하지 않는 모든 던져 실행시 액세스 할 때 NotSupportedException. 즉, IList 인터페이스를 구현하지만 실행시이 동일한 계약을 위반합니다.

난 정말 불변의리스트를 노출하고 있음을 표현하기 위해, 나는 보통 길이와 ( this CodeProject article에 설명)는 IEnumerable에 인덱서를 추가하는 사용자 정의 IIndexable 인터페이스에 의존. 처음에는 IMHO에서 수행해야했던 래퍼입니다.

-1

나는이 옵션은 아직 언급 보지 못했다 :

private List<string> myList; 

public List<string> MyList 
{ 
    get { return myList.AsReadOnly().ToList(); } 
} 

이 읽기 ​​전용 목록을 노출 할 수 있도록해야한다.

+0

과 함께 사용할 수 있다고 생각합니다. 먼저, 당신은'ReadOnlyCollection '을 생성하여리스트를 감싸줍니다. 이것은'ReadOnlyCollection '의 인스턴스가 변경 가능한 IList 인터페이스를 구현하고 런타임에 수정 될 경우 throw합니다. 그런 다음 원래의 목록은 아니지만 수정 내용을 허용하는 새로운'List '에 모든 내용을 복사 한 후에 해당 컬렉션을 버립니다. 또한이 코드는 변경할 수 없지만 실수로 변경 가능한 복사본 인 변경 가능한 멤버를 노출하므로 오해의 소지가 있습니다. –

3

.NET 4.5 프레임 워크에서는 IReadOnlyList 인터페이스 만 표시 할 수 있습니다. 뭔가 같은 :

private List<string> _mylist; 
public IReadOnlyList<string> myList { get {return _myList;} } 

하거나 IList의

private List<string> _mylist; 
public IReadOnlyList<string> myList { get {return new List<string>(_myList);} }