tags:

views:

127

answers:

4

I am working on a C# application which consists of objects Department, Course, and Section. Each Department has many Courses, and each Course has many Sections. Currently I have three classes: Department, Course, and Section. Department contains some properties and then a List Courses, which contains the courses the department offers. Course contains some properties and then a List Sections, which contains the sections of the course. Is this a good way to have the code structured or should I be doing it a different way?

Secondly, when I instantiate a department in my application, I set some properties and then would like to begin adding courses to the List Courses defined in the Department class. However, I seem to be unable to simply do Department.Courses.Add(Course) from the application. What must I do within the Department class so that I may add objects to that list without breaking the principle of encapsulation?

An example of what I have with the list right now is:

class Department
{

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

however Department.Courses is not available in the program code after the class has been instantiated (all other properties of the class are available).

A: 

As to your second question - without some code or more details its a bit hard - but i'll take a guess.

You're probably not actually creating the list, just declaring it

List<xxxx> _variable;

vs

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

You must create a list to be able to add to it (new List());

Ruddy
+2  A: 

Probably something Similar. There are several ways of soing this. depends upon what your requirements are.

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

There are better ways of doing this. have a look at these tutorials for better insight

Asad Butt
thanks, that was it!
Andrew
That would create a new List<Course> every time its accessed... probably not what you expect, since its never saved back into the member variable.
Ruddy
Ruddy- I think I see what you mean...do you have any suggestions as to how to avoid this?
Andrew
Yeah, just remove the null check and instantiate the list during construction. No reason to overcomplicate things when you control the state. Also, you probably want to return an ICollection or IList, and you might want to get rid of the setter all together.
Chris
@andrew. Depends on the use model i suppose, but i'm guessing you probably don't actually need as "set" - and only need the Get to return the courses member variable, if its null you set it as new `get {if (courses = null) courses = new List<Course>(); return course;}`EDIT: i'm not sure how to format that properly in a comment, but ultimately the return is NOT part of the IF -- even though it looks like it is during in this comment
Ruddy
thanks all for the help
Andrew
A: 

You sound as if you're on the right track. Your second problem could be down to many things. It could be as Ruddy says and that you're not creating the list. It could also be that your Courses List is not public or that you haven't instanciated a new Course object to add.

ChrisBD
+3  A: 

Instantiate the internal Courses list inside the parameterless constructor of your class.

private List<Course> _coursesList;

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

Also, another way to ensure the encapsulation is to provide a method on your Department class to add the courses to it instead of directly exposing the courses list. Something like

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) { ... }

I think in your case it is not a good idea do directly exposes the List because the class List, may provide methods like, Add and Remove which could potentially creates an invalid state on your parent class. So if you choose to expose methods to manipulate the internal collections like I suggested, you could expose an array of Courses to your API clients (remember the arrays are read-only) so your API consumers won't be able to the create side effects on your department class.

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

In addition, you could also implement the IEnumerable interface on your Department class. It would enable you to take advantage of the all LINQ extension methods available in C# 3.0.

I hope it helps, Carlos.

Carlos Loth
+1 for the most complete answer.
ChrisBD