2009-10-19 6 views
6

코드를 살펴보십시오. 엿볼 수있는 시간이 오래 걸리지 않아야합니다. GetCourse() 이후리스트 <T>이 해결되었습니다.

class Teacher 
    { 
     private int _id; 
     public int ID 
     { 
      get { return _id; } 
      set { _id = value; } 
     } 

     private string _message; 
     public string Message 
     { 
      get { return _message; } 
      set { _message = value; } 
     } 

     public Teacher(int id, string msg) 
     { 
      _id = id; 
      _message = msg; 
     } 

     private List<Course> _items; 
     public List<Course> GetCourses() 
     { 
      return _items; 
     } 

     public Teacher() 
     { 
      if (_items == null) 
      { 
       _items = new List<Course>(); 
      } 

      _items.Add(new Course(1, "cpp")); 
      _items.Add(new Course(1, "java")); 
      _items.Add(new Course(1, "cs")); 
     } 

     public void Show() 
     { 
      Console.WriteLine(this._id); 
      Console.WriteLine(this._message); 
     } 

     public void ShowList() 
     { 
      foreach(Course c in _items) 
      { 
       c.Show(); 
      } 
     } 
    } 

    class Course 
    { 
     private int _id; 
     public int ID 
     { 
      get { return _id; } 
      set { _id = value; } 
     } 

     private string _message; 
     public string Message 
     { 
      get { return _message; } 
      set { _message = value; } 
     } 

     public Course(int id, string msg) 
     { 
      _id = id; 
      _message = msg; 
     } 

     private List<Teacher> _items; 
     public List<Teacher> GetTeachers() 
     { 
      return _items; 
     } 

     public Course() 
     { 
      if(_items == null) 
      { 
       _items = new List<Teacher>(); 
      } 

      _items.Add(new Teacher(1, "ttt")); 
      _items.Add(new Teacher(1, "ppp")); 
      _items.Add(new Teacher(1, "mmm")); 
     } 

     public void Show() 
     { 
      Console.WriteLine(this._id); 
      Console.WriteLine(this._message); 
     } 

     public void ShowList() 
     { 
      foreach (Teacher t in _items) 
      { 
       t.Show(); 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Teacher t = new Teacher(); 
      t.ID = 1; 
      t.Message = "Damn"; 

      t.Show(); 
      t.ShowList(); 

      t.GetCourses().Clear(); 

      t.Show(); 
      t.ShowList(); 

      Console.ReadLine(); 
     } 
    } 

Teacher 인스턴스 내의 기본 Course -list 클리어된다 t.GetCourses().Clear();을 호출 _items의 참조를 반환한다.

이 동작을 방지하고 싶습니다. 즉, GetCourse()은 목록을 반환하지만 수정할 수는 없습니다.

어떻게 달성할까요?

답변

15

당신은 목록의 사본을 만들거나 ReadOnlyCollection에 포장 수 : 첫 번째 옵션은 독립적 인 목록을 생성

private List<Course> _items; 
public IList<Course> GetCourses() 
{ 
    return new List<Course>(_items); 
} 

또는

private List<Course> _items; 
public IList<Course> GetCourses() 
{ 
    return new ReadOnlyCollection<Course>(_items); 
} 

- 호출 측을 수정할 수 있습니다을 , 항목을 추가하거나 제거하지만 교사 객체 목록에는 변경 사항이 표시되지 않습니다. 두 번째 옵션은 기존 목록을 감싸는 래퍼 일 뿐이므로 컬렉션에 대한 모든 변경 사항은 래퍼를 통해 표시됩니다. 호출자는 콜렉션을 변경할 수 없습니다.

두 경우 모두 목록에서 참조하는 개체의 데이터가 변경된 경우 해당 변경 사항을 볼 수 있습니다. 변경을 중지하려면 각 Course을 복제해야합니다.

+0

이제 C#에서 어떻게 이루어 졌습니까? 나는 C# 루프를 벗어났다. 그러나 그런 새로운리스트를 만들거나 어떻게 든리스트를 복제 하겠는가? 목록에 전체 목록을 복사하는 방법이 포함되어 있다고 의심됩니다. –

+2

@ 토마스 : 딥 클론을 만들려면 'List '에 아무것도 없다고 생각합니다. 복제는 내 경험으로 크게 낙담됩니다. –

5

대신 IEnumerable<Course>을 반환하는 것은 어떻습니까?

약간 주제 오프

: 당신이 정말로 등등, 추가 해제 할 수 있습니다 목록을 반환 할 경우, 당신은 아마 어쩌면 대신 List<T>Collection<T>, 또는 인터페이스도 하나를 반환해야합니다, 예 : ICollection<T>. 일반적으로 나는 당신이 할 수있는 가장 제한적인 타입을 반환해야한다고 말하고 싶습니다. 나중에 그것을 좁히는 것보다 느슨한 것이 더 쉽기 때문입니다.

+0

발신자가 그 번호를 다시 목록으로 캐스팅 할 수 있으며 여전히 기본 목록을 수정합니다. –

관련 문제