列表<T>已清除问题

use*_*312 6 c# list

请看一下代码.瞥一眼就不用花很长时间了.

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

由于GetCourse()返回_items的引用,因此调用t.GetCourses().Clear();正在清除实例中的基础Course-list Teacher.

我想阻止这种行为.也就是说,GetCourse()它将返回一个列表,但它不可修改.

怎么实现呢?

Jon*_*eet 15

您可以创建列表的副本,或将其包装在ReadOnlyCollection中:

private List<Course> _items;
public IList<Course> GetCourses()
{
    return new List<Course>(_items);
}
Run Code Online (Sandbox Code Playgroud)

要么

private List<Course> _items;
public IList<Course> GetCourses()
{
    return new ReadOnlyCollection<Course>(_items);
}
Run Code Online (Sandbox Code Playgroud)

第一个选项创建一个独立列表 - 调用者将能够修改它,添加或删除项目,但这些更改将不会显示在教师对象的列表中.第二个选项只是现有列表的包装器 - 因此通过包装器可以看到对集合的任何更改.调用者将无法对集合进行任何更改.

请注意,在这两种情况下,如果Course列表引用的对象的数据发生了更改,则这些更改将以任何方式显示 - Course如果要停止发生,则必须克隆每个更改.

  • @Thomas:我认为`List <T>`中没有任何东西可以创建深度克隆.根据我的经验,基本上不鼓励克隆. (2认同)

Svi*_*ish 5

如何回归IEnumerable<Course>呢?

稍微偏离主题:如果你真的想要返回一个可以添加,清除等等的列表,你应该返回一个Collection<T>而不是一个List<T>,或者甚至一个接口,例如ICollection<T>.一般来说,我会说你应该总是返回限制最多的类型,因为这样放松的东西比以后缩小它更容易.