2009-10-19 17 views
6

請看看代碼。不用花很長時間就可以窺見一斑。列表<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(); 
     } 
    } 

GetCourse()由於返回_items的基準,稱t.GetCourses().Clear();正在清除底層Course -list在Teacher實例。

我想防止這種行爲。即,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對象的數據已更改,那麼這些更改將以任何方式可見 - 如果要停止這種情況,您必須克隆每個Course

+0

這是如何在C#中完成的?我不在C#循環中,但是你會創建一個新的List嗎?或者你會以某種方式克隆這個列表?我懷疑List包含一個深度複製列表的方法。 – 2009-10-19 13:57:00

+2

@Thomas:我認爲'List '中沒有任何東西可以創建深層克隆。根據我的經驗,基本上不鼓勵克隆。 – 2009-10-19 14:00:09

5

如何返回IEnumerable<Course>而不是?

稍微偏離主題:如果你確實想返回可以添加到,清除,等等的列表,你應該返回Collection<T>而不是List<T>,或者也許接口連一個,例如ICollection<T>。總的來說,我會說你應該總是回報你可以限制的最嚴格的類型,因爲放鬆這類事情比稍後放寬它更容易。

+0

來電者可以將其轉換回列表,並仍然修改潛在列表。 – 2009-10-19 14:09:37