2009-10-19 16 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(); बुला Teacher उदाहरण में अंतर्निहित Course -List समाशोधन है।

मैं इस व्यवहार को रोकना चाहता हूं। यही है, 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

क्या यह सी # में किया गया है? मैं सी # लूप से बाहर हूं, लेकिन क्या आप इस तरह की एक नई सूची बनायेंगे या आप किसी भी तरह से सूची क्लोन करेंगे? मुझे संदेह होगा कि सूची में सूची की गहरी प्रतिलिपि बनाने का एक तरीका है। –

+2

@ थॉमस: मुझे नहीं लगता कि गहरी क्लोन बनाने के लिए 'सूची ' में कुछ भी है। क्लोनिंग काफी हद तक मेरे अनुभव में निराश है। –

5

इसके बजाय IEnumerable<Course> वापस करने के बारे में कैसे?

थोड़ा विषय बंद: तुम सच में एक सूची है कि, करने के लिए जोड़ा जा सकता है को मंजूरी दे दी, वगैरह वापस करना चाहते हैं, तो आप शायद एक List<T> के बजाय एक Collection<T>, या शायद इंटरफेस में से एक वापस आ जाएगी, उदाहरण के लिए ICollection<T>। आम तौर पर मैं कहूंगा कि आपको हमेशा सबसे प्रतिबंधित प्रकार वापस करना चाहिए जो आप कर सकते हैं, क्योंकि इसे बाद में कम करने के लिए चीजों को कम करना आसान है।

+0

एक कॉलर इसे वापस पर सूचीबद्ध कर सकता है और अभी भी अंतर्निहित सूची को संशोधित कर सकता है। –

संबंधित मुद्दे