2009-10-19 9 views
6

Por favor, eche un vistazo al código. No debería tomar mucho tiempo para echar un vistazo.La lista <T> está borrada problema

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

Desde GetCourse() devuelve una referencia de _items, llamando t.GetCourses().Clear(); se despejar el Course -list subyacente en la Teacher ejemplo.

Quiero evitar este comportamiento. Es decir, el GetCourse() devolvería una lista, pero no sería modificable.

¿Cómo lograr eso?

Respuesta

15

Se puede crear una copia de la lista, o envolverlo en ReadOnlyCollection:

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

o

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

La primera opción crea una lista independiente - la persona que llama será capaz de modificarlo , agregar o eliminar elementos, pero esos cambios no se verán en la lista de objetos del profesor. La segunda opción es solo una envoltura alrededor de la lista existente, por lo que cualquier cambio en la colección será visible a través del contenedor. La persona que llama no podrá realizar ningún cambio en la colección.

Nótese que en ambos casos, si los Course objetos referenciados por la lista han cambiado sus datos, estos cambios serán visibles en ambos sentidos - que tendría que clonar cada Course si desea dejar que eso ocurra.

+0

¿Es así como ahora se hace en C#? Estoy fuera del ciclo de C#, pero ¿harías una nueva lista como esa o de alguna manera clonarías la lista? Sospecho que la Lista contiene un método para copiar profundamente la lista. –

+2

@Thomas: no creo que haya nada en 'List ' para crear un clon profundo. La clonación se desaconseja en gran medida en mi experiencia. –

5

¿Qué tal si devuelves IEnumerable<Course>?

ligeramente fuera de tema: Si realmente desea devolver una lista que se puede agregar a, aclaró, etcétera, probablemente debería devolver un Collection<T> en lugar de un List<T>, o tal vez incluso una de las interfaces, por ejemplo ICollection<T>. En general, diría que siempre debería devolver el tipo más restrictivo que pueda, ya que es más fácil relajar cosas así que limitarlo más adelante.

+0

Una persona que llama podría devolverlo a la lista y aún modificar la lista subyacente. –

Cuestiones relacionadas