2015-01-27 6 views
3

궁금한 점이 있으면 C#에서 컬렉션을 만드는 두 가지 방법을 발견했습니다. 나에게는 그것은 단지 스타일 일 뿐이지 만 또 다른 설명이있을 수 있습니다. 공연? 이것은 패턴과 일치합니까? 예제 2에서 볼 수있는 유일한 방법은 컬렉션을 덮어 쓰지 못하게하는 것입니다.컬렉션에 요소를 추가하는 방법

예 1

public class Employee 
{ 
    ... 
    public List<Phone> Phones 
    { 
     get; set; 
    } 
    ... 
} 

겠어요 - 예

Employee employee = new Employee(); 
employee.Phones = this.GetPhones(); 

다른 클래스에서 2 :

public class Employee 
{ 
    ... 
    private List<Phone> colPhones; 
    public List<Phone> Phones 
    { 
     get 
     { 
     if(this.Phones == null) 
     { 
      this.Phones = new List<Phone>(); 
     } 
     return this.Phones; 
     } 
    } 
    ... 
    public void AddPhone(Phone phone) 
    { 
     this.Phones.Add(phone); 
    } 
} 

겠어요 -

Employee employee = new Employee(); 
List<Phone> phones = this.GetPhones(); 
//--> Here, I know I can use for(int i....) instead of foreach. This is just for the example. 
foreach(Phone phone in phones) 
{ 
    employee.Phones.Add(phone); 
} 


UPDATE : 내가 허용 대답과 같은 개념 인 마틴 파울러의 책 이름을 "리팩토링"을 읽고 있었다 때이 링크 Encapsulate collection을 발견

.

+1

예 2 "개인 목록 colPhones;" 사용하지 않은 것처럼 보입니다. 이전에 프로그램을 다시 작성한 결과물입니까? – RenniePet

+1

사용해야합니다. 'Phones' getter 안에'this.Phones' 대신'this.colPholes'를 참조해야합니다. 그렇지 않으면 속성에 액세스 할 때마다 StackOverflowExceptions를 계속 throw하는 순환 참조를 얻게됩니다. – krillgar

답변

1

제 생각에는 첫 번째 예가 다소 위험합니다. 컬렉션의 "덮어 쓰기"에 취약하다는 자신을 말하지만, 너무 조심하지 않으면 컬렉션의 미묘한 수정에 취약 할 수 있다고 생각합니다.

Employee employee = new Employee(); 
List<Phone> obscureTemporaryVariable = this.GetPhones(); 
employee.Phones = obscureTemporaryVariable; 
... 
// much later, after having forgotten all about the above bit of code 
obscureTemporaryVariable.Clear(); 
obscureTemporaryVariable.Add(new Phone(42)); 

이제 "직원"의 전화 번호가 수정되었을 가능성이 있습니다 (의도하지 않은 것 같습니다).

+1

또한 두 번째 예제는 "낯선 사람과 이야기하지 마십시오"원칙을 잘 준수합니다. – Dzyann

+0

두 예제 모두 구성원을 수정할 수 있다는 점을 제외하고는. 컬렉션에서 아무 것도 수정되지 않도록하려면'readonly' 속성을 만들고 생성자를 통해서만 속성을 설정해야합니다. – krillgar

+0

마틴 파울러 (Martin Fowler)에서 "리 팩터링 (Refactoring)"이라는 책을 읽고 있었기 때문에 대답을 받아 들였습니다. 여기에는 책을 아주 잘 요약 한 그림이 있습니다. http://refactoring.com/catalog/encapsulateCollection.html 나는이 전략의 동기를 읽었으며 당신이 말한 것과 매우 흡사합니다. 귀하의 답변에 감사드립니다. –

1

다음 코드를 수행하면 전용 멤버 변수가 코드의 IL 수준에서 만들어집니다.

public List<Phone> Phones { get; set; } 

두 번째 방법은 지연로드를 구현하는 방법입니다. 일반적으로 this.Phones = new List<Phone>();을 수행하는 대신 데이터베이스에서 컬렉션을 생성하는 방법이 제공됩니다. 두 번째 시나리오를 사용하는 또 다른 이유는 기존 컬렉션을 덮어 쓰지 않고 속성을 참조 할 때 NullReferenceException에 대해 걱정할 필요가 없기 때문입니다.

상황의 95 %에 대해 첫 번째 시나리오는 좋을 것입니다.

두 예제 모두 employee.Phones.Add(new Phone())을 수행하기 위해 Employee 클래스의 사용자를 중지시키는 방법은 없습니다. readonly 속성을 만들지 않으면 컬렉션 수정을 방지 할 수 없지만 Employee 클래스의 생성자에서만 설정할 수 있으므로 AddPhone() 메서드는 사용할 수 없게됩니다.

관련 문제