public void SetInformationFromInput()
        {
            const string UPROGRAM_NAME_USER_PROMPT   = "Please enter a UProgram's name: ";
            const string DEPARTMENT_HEAD_USER_PROMPT = "Please enter the department's head first and last name: ";
            const string DEGREE_COUNT_USER_PROMPT    = "Please enter the number of degrees offered by this UProgram: ";

            /*
                    If it throws during input gathering, we want to make
                    sure, our Student object will not be corrupted.
                    We could define new variables to save user input to,
                    and then after we were fairly confident that input was
                    good to go, we would set it to object's fields, however...

                    But what if, though highly unlikely, setters throw?
                    That would leave our object half-mutated and with corrupt
                    data. Fortunately, we can pay the price of caching
                    object's fields and simply restore object's values in
                    the catch block if something does go wrong. Hence,
                    no need to define new variables just to collect user data.
               */

            string uProgramNameFieldCopy   = Name;
            string departmentHeadFieldCopy = DepartmentHead;

            // we won't be altering any internals of Degree objects inside the
            // _degrees so all we need is a copy of the collection.

            Degree[] degreesFieldCopy      = new Degree[_degrees.Count];
            _degrees.CopyTo(degreesFieldCopy, 0);

            try
            {

                #region input gathering

                Console.WriteLine(UPROGRAM_NAME_USER_PROMPT);
                Name = Console.ReadLine();

                Console.WriteLine(DEPARTMENT_HEAD_USER_PROMPT);
                DepartmentHead = Console.ReadLine();

                Console.WriteLine(DEGREE_COUNT_USER_PROMPT);
                int newDegreesCount = Int32.Parse( Console.ReadLine() );

                IList<Degree> newDegrees = new List<Degree>(newDegreesCount);

                // delegate user input collection to newly initialized
                // Degree objects.

                for (int i = 0; i < newDegreesCount; ++i) {
                    newDegrees.Add(new Degree());
                    // newDegrees.Count - 1 is the same as i, however, we want to
                    // make sure we indeed to write to the newly created object
                    newDegrees[newDegrees.Count - 1].SetInformationFromInput();
                }
                _degrees = newDegrees;

                #endregion

            }
            catch {

                #region restoring fields

                Name = uProgramNameFieldCopy;
                DepartmentHead = departmentHeadFieldCopy;

                // Degree objects inside degreesFieldCopy are not altered,
                // so we just reassign the reference to it.
                _degrees = degreesFieldCopy;

                #endregion

                throw;
            }
        }
 public void AddDegree(Degree degree)
 {
     if (degree == null) {
         throw new ArgumentNullException("degree");
     }
     _degrees.Add(degree);
 }
 public bool RemoveDegree(Degree degree)
 {
     if (degree == null) {
         throw new ArgumentNullException("degree");
     }
     return _degrees.Remove(degree);
 }
        static void Main()
        {
            #region Instantiating 3 Student objects

            var student1 = new Student {
                FirstName       = "Billy",
                LastName        = "Jackson",
                BirthDate       = new DateTime(1990, 12, 12),
                AddressLine1    = "5th Avenue",
                AddressLine2    = String.Empty,
                City            = "Dodge City",
                StateProvince   = "Kansas",
                ZipPostal       = "67801",
                Country         = "U.S.A."
            };

            var student2 = new Student {
                FirstName       = "Eric",
                LastName        = "Kruger",
                BirthDate       = new DateTime(1992, 4, 16),
                AddressLine1    = "Mastodon Avenue, Seattle, Washington",
                AddressLine2    = String.Empty,
                City            = "Seattle",
                StateProvince   = "Washington",
                ZipPostal       = "98113",
                Country         = "U.S.A."
            };

            var student3 = new Student {
                FirstName       = "Jeremy",
                LastName        = "Pokluda",
                BirthDate       = new DateTime(1991, 1, 24),
                AddressLine1    = "Jamestown Boulevard, Jackson, Minnesota",
                AddressLine2    = String.Empty,
                City            = "Jackson",
                StateProvince   = "Minnesota",
                ZipPostal       = "55003",
                Country         = "U.S.A."
            };

            #endregion

            #region Instantiating a Course object

            var csCourse = new Course {
                Name            = "Programming with C#",
                Credits         = 20,
                DurationInWeeks = 4
            };

            #endregion

            #region Adding 3 Students to the Course object

            csCourse.AddStudent(student1);
            csCourse.AddStudent(student2);
            csCourse.AddStudent(student3);

            #endregion

            #region Instantiating a Teacher object

            var teacher = new Teacher {
                FirstName       = "Jimmy",
                LastName        = "Johnes",
                BirthDate       = new DateTime(1970, 1, 7),
                AddressLine1    = "38th Street, Montgomery, Alabama",
                AddressLine2    = String.Empty,
                City            = "Montgomery",
                StateProvince   = "Alabama",
                ZipPostal       = "36109",
                Country         = "U.S.A."
            };

            #endregion

            #region Adding the Teacher object to the Course object

            csCourse.AddTeacher(teacher);

            #endregion

            #region Instantiating a Degree object

            var bachelorsDegree = new Degree {
                Name            = "Bachelor of Science",
                CreditsRequired = 120
            };

            #endregion

            #region Adding the Course object to the Degree object

            bachelorsDegree.AddCourse(csCourse);

            #endregion

            #region Instantiating a UProgram object called Information Technology

            var uProgram = new UProgram {
                Name            = "Information Technology",
                DepartmentHead  = "Leland Stanford"
            };

            #endregion

            #region Adding the Degree object to the UProgram object

            uProgram.AddDegree(bachelorsDegree);

            #endregion

            #region Output
            string uProgramOutputFormatString = "The {0} contains the {1} degree";
            string degreeOutputFormatString   = "The {0} degree contains the course {1}";
            string courseOutputFormatString   = "The {0} contains {1} student{2}";

            foreach (var degree in uProgram.Degrees) {
                Console.WriteLine(uProgramOutputFormatString, uProgram.Name, degree.Name);
                Console.WriteLine();
                foreach (var course in degree.Courses) {
                    Console.WriteLine(degreeOutputFormatString, degree.Name, course.Name);
                    Console.WriteLine();

                    int studentCount = course.Students.Count;
                    Console.WriteLine(courseOutputFormatString, course.Name, studentCount, (studentCount > 1) ? "s" : String.Empty);
                    Console.WriteLine();
                }
            }
            #endregion
        }