Using Array of Arrays for One to Many Relationship in C# - c#

I am making a console test with C#.
Actually I have never used of C# but VB.Net. I want to create arrays for one-to-many relationship.
My one is 'A Student' has 'Name','Sex',...,'Courses Taken'.
A Student would take many course, each course has a Title and Included Subject. Each subject has Name, Description and Point.
Like this.
Student
- Name - Sex - Courses Taken
Take Courses
- Course Title - Subject Included
Subject
- Subject Name [Math] [MVC]
- Subject description [Advance] [Building Website]
- Subject Point [6.9] [5.6]
I want to store each entity in Arrays but I don't know how to connect subjects/courses to each Students. And how can I get Student who attending Math or MVC. Because every students can have more then more course/ more than one subjects.

You'll want to create classes to describe your different objects.
class Student
{
string Name { get; set; }
Gender Sex { get; set; } // write an enum for this
IEnumerable<Course> CoursesTaken { get; set; }
}
class Course
{
string Title { get; set; }
Subject Subject { get; set; }
}
class Subject
{
string Name { get; set; }
string Description { get; set; }
double Points { get; set; }
}
Using List to create enumerations of instances of these new types allow you to use LINQ to select or evaluate members of the list (nested for loops work as well):
// populate a list of students called studentList
//...
// use LINQ to select the students you want
var mathResults = studentList.Where(student => student.CoursesTaken.Any(course => course.Subject.Name == "Math"));

I feel like I've done with it in good way...
Pls check my code for my ques! ^^
I first made 3 classes as below..
class Students
{
public string StudentName;
public int StudSize;
public bool StudSex;
public List<Take_Courses> tcourses;
public Students() { }
public Students(string name, int size, bool sex, List<Take_Courses> tcourses)
{
StudentName = name;
StudSize = size;
StudSex = sex;
this.tcourses = tcourses;
}
}
and
class Take_Courses
{
public string classname;
public List<Arr_Courses> arr_Course;
public Take_Courses() { }
public Take_Courses(string classname, List<Arr_Courses> arr_courses)
{
this.classname = classname;
arr_Course = arr_courses;
}
}
class Arr_Courses
{
public string cosname;
public string cosdesc;
public float cospoint;
public Arr_Courses() { }
public Arr_Courses(string name, string description, float point)
{
cosname = name;
cosdesc = description;
cospoint = point;
}
}
I then initialized values in Main class as below;
Arr_Courses acos=new Arr_Courses();
Arr_Courses acos1=new Arr_Courses("Math","Advance Math1",9.5f);
Take_Courses cos=new Take_Courses();
Take_Courses cos_take1=new Take_Courses("Info Tech",new List<Arr_Courses>{acos1});
Students stu=new Students();
Students Stu1 = new Students("Milla", 22, true,new List<Take_Courses>{cos_take1});
I then make another List to be generated names of student and use for looping and assign each one to List.
I think some important part is this.
if (arr_stud[i].tcourses[j].arr_Course[k].cosname.Equals("Math"))
{
Math_Stud++;
MathStudents[i] = arr_stud[i];
}
I am sharing this if anyone needs something like this. Any ungraded codes is appreciated to be shared. Thanks so so.

Related

Is it normal to have a list of objects in an object?

I'm new to OO design, and I wondering whether it is typical to have designs where objects contain lists of other objects. An example is below:
// Person object containing a list of phone numbers
public class Person
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Phone> Contacts { get; set; }
public void AddPhoneNumber(Phone phone)
{
Contacts.Add(phoneNumber);
}
}
// Phone object
public class Phone
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Number { get; set; }
}
// Example code to establish an object:
Person p1 = new Person();
p1.FirstName = "John";
p1.LastName = "Smith";
p1.AddPhoneNumber(new Phone() { Number = "555957000" });
p1.AddPhoneNumber(new Phone() { Number = "555579561" });
Is there a better way to structure this that simplifies the design and allows easier access to the data? Thanks!
Yes, it is absolutely fine to have an object contains list of object. In OOPs this is called Composition, which represent strong relationship between participating class.
I wondering whether it is typical to have designs where objects
contain lists of other objects.
Absolutely, this is normal as an object can contain lists that belong to only that particular object. One of many examples is when you're traversing a binary tree or such you could have each node have their own list which identifies their children. There are many more cases in which an object should/could contain their own list.
Going back to your code, you seem to have an error because the code below states that the list will contain Phone objects.
public List<Phone> Contacts { get; set; }
but yet you're passing in a string object rather than a phone object.
public void AddPhoneNumber(string phoneNumber)
{
Contacts.Add(phoneNumber); // this code shouldnt compile
}
rather what you can do is this:
public void AddPhoneNumber(string phoneNumber)
{
Contacts.Add(new Phone() { Number = phoneNumber });
}
There's nothing wrong with your code. It's perfectly valid to have a list of objects within an object.
Though adding a string to your List of Phone objects will throw an error.
You can add a phone number like so:
Person p1 = new Person();
p1.Contacts.Add(new Phone() { Number = "555579561" });

Will these code be safe in memory in c#?

I have a question about the following code.
First, these codes worked well.
However, there is no declaration only defined about “courses” in class Student.If in the Constructor of Student the argument is constant, will these code be safe?
Thanks for helping!:)
public class Student
{
public string name;
public int age;
public string[] courses;
public Student(string _name, int _age,params string[] _courses)
{
name = _name;
age = _age;
courses = _courses;//is this OK if _courses is constant?
}
}
public class work : MonoBehaviour
{
void Start()
{
/*
string[] courses={"math", "English"};
Student Tom = new Student("Tom",18,courses);
//It's wrong!
*/
Student Tom = new Student("Tom", 18, "math", "English");
string Tom_text = JsonUtility.ToJson(Tom);
Debug.Log(Tom_text);
}
}
The way you have it, anyone can change the Student object at anytime.
If you do not want anyone changing anything about the Student object once it has been created, then make it immutable like this:
public class Student
{
public string Name { get; private set; }
public int Age { get; private set; }
public IEnumerable<string> Courses { get; private set; }
public Student(string name, int age, params string[] courses)
{
this.Name = name;
this.Age = age;
this.Courses = courses;
}
}
Now people cannot change the the properties because the setters are private.
And to follow the .NET naming convention, do not use - underscores in parameter names and use Pascal Notation for property names. I have removed the underscores and used Pascal Notation for property names.
EDIT
#diemaus mentioned a good point in the comments to this answer, in C# 6:
You can actually remove the private set entirely, and just leave it { get; }. This is allowed as long as long as you only set the properties in the constructor.

C# map two complex objects

I have four classes :
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Product> Product { get; set; }
}
public class Product
{
public int ProductNumber { get; set; }
public string ProductColor { get; set; }
}
///////////////////////////////////////////////
public class Customer_
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Article> Article { get; set; }
}
public class Article
{
public int ArticleNumber { get; set; }
public string ArticleColor { get; set; }
}
And one instance :
var Cus = new List<Customer>
{
new Customer()
{
FirstName = "FirstName1",
LastName = "LastName1",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor1",
ProductNumber = 11
}
}
},
new Customer()
{
FirstName = "FirstName2",
LastName = "LastName2",
Product = new List<Product>
{
new Product()
{
ProductColor = "ProductColor2",
ProductNumber = 12
}
}
}
};
I want to create a new object List<Customer_> with the value of my instance Cus. For example Customer.FirstName = Customer_.FirstName, Customer.Product.ProductColor = Customer_.Article.ArticleColor etc
What is the best way to do this easily, could one use a Dictionary?
Mapping can be accomplished through the use of an Interface.
Define an interface(s) which provide a mapping of logically named properties such as the common color properties you mention:
// Some entities have different named properties but can be joined
// using those properties. This interface shows a common color which
// when implemented will route the processing to a common shared property
// which reports and sets the associated color.
public interface IDefinedColor
{
string Color { get; set; }
}
If you have to create partial classes for Product and Article and have them adhere to said interfaces. Hint if using an entity mapper such as EF this is a great way to do such maping using partials. Implement implement the interface and hook up the commonality:
// Holds the common properties for future processing.
public partial class Product : IDefinedColor
{
public string Color
{
get { return ProductColor; }
set { ProductColor = value; }
}
}
Then work off of the IDefinedColor mapped implementations as needed.
By using interfaces one is letting all future developers know of the contract which specifies a business logic equality in the properties and it is not hidden in other joining classes.
You could create a mapper extension class
public static class MapperExtension
{
public Customer_ Convert(this Customer customer)
{
return new Customer_()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Article = customer.Product.Convert()
};
}
public static List<Article> Convert(this List<Product> products)
{
return products.Select(x=> new Article(){
ArticleNumber = x.ProductNumber,
ArticleColor = x.ProductColor
};
}
}
make sure you reference the proper namespace where you place the extension class.
Call the code like this
Where customers is a List filled from your code
List<Customer_> convertedCustomers_ = customers.Select(x=> x.Convert()).ToList();
It depends on the relationhip between those components but I would simply add constructor to Customer_ that accepts a Customer object. And then you invoke that do perform the conversion. e.g.
public class Article
{
public Article(Product source)
{
this.ArticleNumber = source.ProductNumber;
this.ArticleColor = source.ProductColor;
}
}
public class Customer_
{
public Customer_(Customer source)
{
this.FirstName = source.FirstName;
this.LastName = source.LastName;
this.Article = source.Product.Select(o => new Article(o)).ToList()
}
...
}
//and finally to convert the list you can do something like
//initial list
var Cus = new List<Customer>() { ... etc. }
/converted list
var Cus_ = Cus.Select(o => new Cusomter_(o)).ToList();
Edit: I see from your comment above that you actually have 100 properties to map. I can see this is a pain. But if you have complex transformations like Product to Article then I would still go the manual route as above so you can be completely clear about what is going on. Alternatively you could look to use inheritance to redesign your objects with common base classes or interfaces, that would probably make mapping easier.

Creating a List of Classes that contains a List of a Class

I'm studying C# Classes and am trying to create a program that has a Class called Employee and derived classes of ProductionWorker, ShiftSupervisor, and TeamLeader.
I have a list box where I want to display All the employees, and within the program, there's functionality to add, edit, or remove respective people, but rather than making 3 lists like so:
List<ProductionWorkers> pWorkers = new List<ProductionWorkers>();
List<ShiftSupervisor> sSupervisors = new List<ShiftSupervisor>();
List<TeamLeader> tLeaders = new List<TeamLeader>();
I'd like to be able to have the Employee base class have or contain some sort of list of it's derived classes and their objects.
For example I'd like to be able to be able to Add and Remove derived objects to a list of Employees in some fashion, given the following example:
List<Employee> employees = new List<Employee>();
ProductionWorker _pWorker = new ProductionWorker();
_pWorker.Name = "Bob";
_pWorker.EmployeeID = 1234;
employees.Add(_pWorker));
I don't know if that's even possible or realistic to do that, but it would seem maybe there is a way from what I've read, I'm just not sure how to implement it. I'm open to better suggestions however, if someone knows of a better or proper way to get all the Employees listed into a ListBox without having to cycle through 3 different lists of the different derived classes.
For clarity, below is the Base class, then its following derived classes.
public class Employee
{
public string Name { get; set; }
public int EmployeeNumber { get; set; }
}
class ProductionWorker : Employee
{
public int ShiftNumber { get; set; }
public decimal HourlyPayRate { get; set; }
}
class TeamLeader : ProductionWorker
{
public int ReqHours { get; set; }
public int AttendedHours { get; set; }
}
class ShiftSupervisor : Employee
{
public int Salary { get; set; }
public int AnnualProductionBonus { get; set; }
}
I didn't realize until I posted my classes here that Team Leader is actually a derived class of Production Worker. I'm not sure if that changes things...
Yes, you can add Employee items and items deriving from Employee to the employees list.
List<Employee> employees = new List<Employee>();
ProductionWorker pWorker = new ProductionWorker {
Name = "Bob",
EmployeeID = 1234
};
employees.Add(pWorker);
If you want to display all these different kinds of employees in the same listbox, override the ToString method in these classes. The ListBox will automatically use it in order to display the items.
public class ProductionWorker : Employee
{
public override string ToString()
{
return String.Format("{0} ({1}), production", Name, EmployeeID);
}
}
You can assign the list of employees to the listbox like this
employeeListBox.DataSource = employees;
From the employees list you can access the members declared in Employee directly:
int id = employees[i].EmployeeID;
However; you need to cast, if you want to access members of derived types
int salary = 0;
var supervisor = employees[i] as ShiftSupervisor;
if (supervisor != null) {
salary = supervisor.Salary;
}
If you know the type of an item in advance you can cast directly
int salary = ((ShiftSupervisor)employees[0]).Salary;

VS 2010 Report Viewer Cannot Access Nested Collections, Anyone?

I have gone through all the walk through on MSDN as usual they are worthless - extremely limited.
If I make the internal object in my class a single class I can display the information, but as soon as I convert it to a list of objects ( a collection ) I get the #Error in the display.
Here is an updated example.
For an example I have a Person object that can have one or more phone numbers ( list of numbers ) and I cannot find a way to access the phone numbers.
[Serializable]
public class Person
{
private readonly List<PhoneNumber> _numbers = new List<PhoneNumber>();
public Person()
{
}
public Person(int id, string name, string address, decimal salary)
{
Id = id;
Name = name;
Address = address;
Salary = salary;
}
public void AddNumber(PhoneNumber number)
{
_numbers.Add(number);
}
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public List<PhoneNumber> PhoneNumbers { get { return _numbers; } }
}
[Serializable]
public class PhoneNumber
{
public PhoneNumber()
{
}
public PhoneNumber(int id, string areaCode, string phone)
{
AreaCode = areaCode;
Id = id;
Phone = phone;
}
public string AreaCode { get; set; }
public string Phone { get; set; }
public int Id { get; set; }
}
I then populate the collections.
var persons = new List<Person>();
var t = new Person(1, "Mike", "5150 Nuts", 125);
t.AddNumber(new PhoneNumber(1, "425", "455"));
t.AddNumber(new PhoneNumber(1, "425", "450"));
persons.Add(t);
t = new Person(2, "Tom", "1055 MS HAS NO DOCUMENTATION AS USUAL!", 1245);
t.AddNumber(new PhoneNumber(2, "TYPICAL", "OF-THEM"));
t.AddNumber(new PhoneNumber(2, "ANY", "ONE???"));
persons.Add(t);
I then assign everything to the report.
reportViewer1.ProcessingMode = ProcessingMode.Local;
reportViewer1.LocalReport.ReportPath = "..\\..\\Report1.rdlc";
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("Person",persons));
reportViewer1.RefreshReport();
In the report it displays the people will display without issue as I add the text boxes to a list and then group the list by Id. When I try to display the phone numbers, I get the #ERROR message, and for the life of me I cannot seem to find a way to display the list of numbers that are assigned to a person.
If I change the object from List<PhoneNumber> within the person class to PhoneNumber I can access it, but when trying to display a List<PhoneNumber> I cant.
I need to be ale to display List<of objects> within an Class Item.
The nested collection must be displayed as a subreport where the nested collection is an separate data source. You must bind the event LocalReport.SubreportProcessing to a handler that will filter and bind the datasource (PhoneNumbers) to the subreport as a seperate report data source. The example at the link provided should get you where you need to go.

Categories