列表<t>已清除问题</t>

时间:2009-10-19 13:51:43

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

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

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

如何实现?

2 个答案:

答案 0 :(得分: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停止发生这种情况。

答案 1 :(得分:5)

如何返回IEnumerable<Course>呢?

稍微偏离主题: 如果你确实想要返回一个可以添加,清除等等的列表,你应该返回一个{ {1}}代替Collection<T>,甚至可能是其中一个接口,例如List<T>。一般来说,我会说你应该总是返回最具限制性的类型,因为这样放松的东西比以后缩小它更容易。