2009-10-19 23 views
6

Vui lòng xem mã. Nó không nên mất nhiều thời gian để có một cái nhìn thoáng qua.Danh sách <T> bị xóa sự cố

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(); 
     } 
    } 

Kể từ GetCourse() trả về một tham chiếu của _items, gọi t.GetCourses().Clear(); được xóa cơ bản Course -list trong Teacher dụ.

Tôi muốn ngăn chặn hành vi này. Tức là, GetCourse() sẽ trả về một danh sách nhưng nó sẽ không thể sửa đổi được.

Làm cách nào để đạt được điều đó?

Trả lời

15

Bạn có thể tạo một bản sao của danh sách, hoặc bọc nó trong ReadOnlyCollection:

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

hoặc

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

Tùy chọn đầu tiên tạo ra một danh sách độc lập - người gọi sẽ có thể sửa đổi nó , thêm hoặc xóa các mục, nhưng những thay đổi đó sẽ không được nhìn thấy trong danh sách đối tượng của giáo viên. Tùy chọn thứ hai chỉ là một trình bao bọc xung quanh danh sách hiện có - vì vậy mọi thay đổi đối với bộ sưu tập sẽ hiển thị thông qua trình bao bọc. Người gọi sẽ không thể thực hiện bất kỳ thay đổi nào đối với bộ sưu tập.

Lưu ý rằng trong cả hai trường hợp, nếu Course đối tượng được tham chiếu bởi danh sách có thay đổi dữ liệu, những thay đổi đó sẽ hiển thị theo cách - bạn phải sao chép mỗi Course nếu bạn muốn dừng điều đó xảy ra.

+0

Đây có phải là cách thực hiện trong C# ngay bây giờ không? Tôi ra khỏi vòng lặp C#, nhưng bạn sẽ tạo một Danh sách mới như vậy hay bạn sẽ sao chép danh sách? Tôi nghi ngờ rằng Danh sách chứa một phương pháp để sao chép sâu vào danh sách. –

+2

@Thomas: Tôi không nghĩ có bất kỳ điều gì trong 'Danh sách ' để tạo bản sao sâu. Nhân bản phần lớn là nản chí trong kinh nghiệm của tôi. –

5

Thay vào đó hãy trả lại số IEnumerable<Course>?

Hơi off topic: Nếu bạn thực sự muốn trở lại một danh sách có thể được thêm vào, xóa, vân vân, có lẽ bạn nên trả về một Collection<T> thay vì một List<T>, hoặc thậm chí có thể là một trong những giao diện, ví dụ: ICollection<T>. Nói chung tôi sẽ nói rằng bạn nên luôn luôn trả về loại hạn chế nhất mà bạn có thể, vì nó dễ dàng hơn để nới lỏng những thứ như thế hơn là thu hẹp nó sau này.

+0

Một người gọi có thể truyền trở lại Danh sách và vẫn sửa đổi danh sách cơ bản. –

Các vấn đề liên quan