【问题标题】:C# class organization and listsC# 类组织和列表
【发布时间】:2011-01-12 04:00:43
【问题描述】:

我正在开发一个 C# 应用程序,它由对象 Department、Course 和 Section 组成。每个部门都有很多课程,每个课程都有很多科室。目前我有三个班:部门,课程和科。 Department 包含一些属性,然后是 List Courses,其中包含部门提供的课程。 Course 包含一些属性,然后是 List Sections,其中包含课程的各个部分。这是构建代码结构的好方法还是我应该以不同的方式来做?

其次,当我在我的应用程序中实例化一个部门时,我设置了一些属性,然后想开始将课程添加到部门类中定义的 List Courses 中。但是,我似乎无法简单地从应用程序中执行 Department.Courses.Add(Course)。我必须在 Department 类中做什么才能在不破坏封装原则的情况下将对象添加到该列表中?

我现在拥有的列表的一个例子是:

class Department
{

     // ......
     List<Course> Courses = new List<Course>;
}

然而,在类被实例化后,Department.Courses 在程序代码中不可用(类的所有其他属性都可用)。

【问题讨论】:

  • 尝试将课程对象添加到列表时遇到什么错误?

标签: c# oop list


【解决方案1】:

在类的无参数构造函数中实例化内部课程列表。

private List<Course> _coursesList;

public Department()
{
    _coursesList = new List<Course>();
}

另外,确保封装的另一种方法是在您的 Department 类上提供一种方法来将课程添加到其中,而不是直接公开课程列表。类似的东西

public void AddCourse(Course c) { ... }

// or (adding the feature of doing the method calls in a composable way)
public Course AddCourse(Course c) { ... }

// or 
public void AddCource(String name, etc) { ... }

我认为在您的情况下,直接公开 List 不是一个好主意,因为 List 类可能提供诸如 Add 和 Remove 之类的方法,这可能会在您的父类上创建无效状态。因此,如果您选择像我建议的那样公开操作内部集合的方法,您可以向您的 API 客户端公开一系列课程(请记住数组是只读的),这样您的 API 使用者将无法创建副作用在你的部门班上。

public Course[] Courses {
    get { return _coursesList.ToArray(); }
}

此外,您还可以在 Department 类上实现 IEnumerable 接口。它将使您能够利用 C# 3.0 中提供的所有 LINQ 扩展方法。

希望对你有帮助 卡洛斯。

【讨论】:

    【解决方案2】:

    可能是类似的东西。有几种方法可以解决这个问题。取决于您的要求。

    public class Department
    {
        // Initialize the list inside Default Constructor
        public Department()
        {            courses = new List<Course>();        }
    
        // Initialize List By Declaring outside and Passing with Dpartment Initilization
        public Department(List<Course> _courses)
        {            courses = _courses;        }
    
        List<Course> courses;
        public List<Course> Courses
        {
            get
            {
                if (courses == null)
                    return new List<Course>();
                else return courses;
            }
            set { courses = value; }
        }
        internal bool AddCourseToCourses(Course _course)
        {
            bool isAdded = false;
            // DoSomeChecks here like
            if (!courses.Contains(_course))
            {
                courses.Add(_course);
                isAdded = true;
            }
            return isAdded;
        }
    }    
    
    public class Course
    {
        public Course(List<Subject> _subject)
        {            subjects = _subject;        }
    
        List<Subject> subjects;  
        public List<Subject> Subjects
        {
            get { return subjects; }
            set { subjects = value; }
        }
    }
    
    // I do not get what do you mean by course "section", very general.
    // used Subject instead, Change as you want just to give an idea
    public class Subject
    {
        string name;    
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    
        int creditHours;    
        public int CreditHours
        {
            get { return creditHours; }
            set { creditHours = value; }
        }
        public Subject(string _name, int _creditHours)
        {
            name = _name;
            creditHours = _creditHours;
        }
    }
    public class TestClass
    {
        public void DoSomething()
        {  
            // Subjects
            Subject subj1 = new Subject("C#", 10);
            Subject subj2 = new Subject(".Net", 10);
    
            // List of Subjects
            List<Subject> advancedPrSubjects = new List<Subject>();
            advancedPrSubjects.Add(subj1);
            advancedPrSubjects.Add(subj2);
    
            // Course
            Course advancedProgramming = new Course(advancedPrSubjects);            
    
    
            // Deliver authoroty to add Course to Department Class itself
            Department dept = new Department();
            dept.AddCourseToCourses(advancedProgramming);
        }
    }
    

    有更好的方法来做到这一点。查看这些教程以获得更好的洞察力

    【讨论】:

    • 每次访问时都会创建一个新的 List... 可能不是您所期望的,因为它从未保存回成员变量中。
    • Ruddy-我想我明白你的意思了......你有什么建议可以避免这种情况吗?
    • 是的,只需删除空检查并在构造过程中实例化列表。当您控制状态时,没有理由使事情变得过于复杂。此外,您可能希望返回 ICollection 或 IList,并且可能希望一起摆脱 setter。
    • @andrew。取决于我想的使用模型,但我猜你可能实际上并不需要作为“设置” - 并且只需要 Get 返回课程成员变量,如果它为空,则将其设置为新的get { if (courses = null) courses = new List&lt;Course&gt;(); return course; } 编辑:我不确定如何在评论中正确格式化,但最终返回不是 IF 的一部分——即使它看起来像是在此评论中
    【解决方案3】:

    关于你的第二个问题 - 没有一些代码或更多细节,这有点难 - 但我会猜测一下。

    您可能实际上并没有创建列表,只是声明它

    List<xxxx> _variable;
    
    vs
    
    List<xxxx> _variable = new List<xxxxx>();
    

    您必须创建一个列表才能添加到它(new List());

    【讨论】:

      【解决方案4】:

      你听起来好像在正确的轨道上。 你的第二个问题可能归结为很多事情。 可能正如 Ruddy 所说,您没有创建列表。 也可能是您的课程列表不公开,或者您没有实例化要添加的新课程对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-03
        • 2020-12-06
        • 2017-02-15
        • 2017-06-15
        • 1970-01-01
        • 2020-12-02
        • 2013-09-28
        • 1970-01-01
        相关资源
        最近更新 更多