2013-06-09 4 views
1

읽기 전용 목록을 만들려면 IReadOnlyList<T>을 조사했습니다. 하지만 100 % 읽기 전용이 아닌 것 같습니다. 목록에서 항목을 추가/제거 할 수는 없지만 구성원을 수정할 수는 있습니다.수업을 진정으로 불변으로 만드는 방법?

이 예제를 고려하십시오.

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Test> list = new List<Test>(); 
     list.Add(new Test() { MyProperty = 10 }); 
     list.Add(new Test() { MyProperty = 20 }); 

     IReadOnlyList<Test> myImmutableObj = list.AsReadOnly(); 

     // I can modify the property which is part of read only list 
     myImmutableObj[0].MyProperty = 30; 
    } 
} 

public class Test 
{ 
    public int MyProperty { get; set; } 
} 

는 정말 읽기 전용 나는 같은 읽기 전용 MyProperty을해야 확인하십시오. 이 클래스는 사용자 정의 클래스이므로 클래스를 수정할 수 있습니다. 내 목록이 getter & setter 속성이 모두 포함 된 inbuilt .net 클래스 인 경우 어떻게합니까? 이 경우 값을 읽을 수있는 .net 클래스의 래퍼를 작성해야한다고 생각합니다.

기존 클래스를 변경하지 못하게 할 수있는 방법이 있습니까?

+0

목록 *은 * 변경할 수 없습니다. 얕은 불변성, 반면 당신은 깊은 불변성을 기대합니다. [Immunability의 종류] (http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx)를 참조하십시오. 다른 중요한 차이점. – delnan

+0

나는 클래스를 ROM에 구운 다음 컴퓨터의 마더 보드에있는 PCIe 슬롯에 맞는 도터 보드에 소켓을 연결합니다. –

+0

@delnan : 아니요. 실제로는 읽기 전용입니다. – SLaks

답변

2

진정한 변경 불가능한 클래스는 속성과 필드가 모두 읽기 전용 인 클래스입니다. 이 정의는이 클래스의 필드와 속성 내에 포함 된 모든 클래스가 읽기 전용이어야한다는 점에서 재귀 적입니다. 읽기 전용 목록은 진정으로 변경되지 않습니다. 왜냐하면 목록의 내용은 수정할 수 있기 때문에 불변하지 않기 때문입니다. 목록에있는 개별 항목은 읽기 전용이어야하며 IReadOnlyList<T>은 진정 변경할 수 없습니다.

6

당신은 용어를 혼동하고 불변 읽기 전용.

읽기 전용 개체는 변경할 방법이없는 개체입니다. ReadOnlyCollection<T> (AsReadOnly()이 반환 됨)이 좋은 예입니다. 그러나 IEnumerable<T>도 읽기 전용입니다.
중요한 차이점은 읽기 전용 개체를 변경할 수 있다는 것입니다.

list.Add(new Test())으로 작성하면 읽기 전용 컬렉션 (단지 list)이 변경됩니다.

읽기 전용 모음은 안전한 API를 디자인 할 때 유용합니다. 컬렉션의 소유자 만이 읽기 전용 모음을 변경할 수 있습니다.
그러나 스레드 안전성에는 아무런 영향이 없습니다.


불변 목적은, 모든에 을 변경할 수 없습니다 무슨 일이 있더라도 (반사 카운트하지 않습니다) 개체입니다. 은 변경 불가능한 클래스의 훌륭한 예입니다. 기존 string 인스턴스의 값은 상황에 관계없이 절대로 변경 될 수 없습니다. (반사, 안전하지 않은 코드 및 특정 마샬링 트릭 제외)

.Net에는 내장 된 불변 인 컬렉션이 없지만 CLR 팀 released a library of immutable collection types on NuGet이 있습니다.

진정으로 변경 불가능한 개체는 본질적으로 스레드로부터 안전합니다. 그것들을 수정할 방법이 없으므로, 다른 스레드가 일관성없는 인스턴스를 관찰 할 가능성은 없습니다.


당신은 약 깊은 불변성을 요구하고 있습니다.
속성 (전체 개체 그래프)을 통해 재귀 적으로 액세스 할 수있는 모든 개체 자체가 깊이 불변 인 경우 개체가 깊이 불변합니다.

참조 할 필요가있는 모든 클래스의 불변 버전을 만들지 않는 한 깊이 변경할 수없는 개체를 만들 수 없습니다. 이 불변의 버젼은 변경 가능한 원의 클래스로부터 상태를 카피 할 필요가 있습니다. 그것들은 단순히 원래 인스턴스를 감쌀 수 없으며, 내부 인스턴스를 통해 여전히 변경 가능할 수 있습니다.

변경할 수있는 클래스 주위에 읽기 전용 래퍼를 만들어 깊이 읽기 전용 개체를 만들 수 있습니다.


자세한 내용은 my blog를 참조하십시오.

+1

개체가 불변 인 경우 * 상태가 캡슐화 된 * 외부 개체는 모두 불변이어야하지만 불변 개체가 해당 개체를 식별하는 데 사용되는 경우 변경 가능한 개체에 대한 참조를 보유 할 수 없음을 의미하지는 않습니다. 그 상태가 아닌 그 객체들 *. 유니 캐스트 대표는 그 대표적인 예입니다. 예를 들어,'Func '는 처음으로 호출 할 때는 1을 반환하고, 2 번째 경우에는 2를 반환 할 수 있습니다.'Method'는 절대로 변경되지 않고'Target '에 의해 참조 된 객체의 신원은 절대 변경되지 않지만 객체 스스로 원하는대로 할 수 있습니다. – supercat

관련 문제