Taking an object and adding it to the appropritae collection - c#

I am doing a few labs and it has me creating multiple classes that are inheriting from a base class. i have created the base class, a student class that inherits from the base class, which creates a student and a teacher class that inherits from the base class, which creates a teacher. Now i am working on creating a school class that does not inherit any class. i have done most of what it is wanting me to do, but i am stuck on creating the appropriate methods to add the objects to its appropriate classes. I need assistance and guidance on how to create these methods so i may proceed. I am just going to post the Student class that i am working in right now and the instructions. I am not looking for someone to do my homework for me, i just cant seem to find anything online that can guide me in the right directions. thank you for your help.
Methods
Add(base) - Takes a teacher/student object and adds it to the
appropriate collection.
Print(base[]) - Private method that takes an
array of your base class object and prints all the elements of the
array.
3 Print(bool students = true) - Public method that prints out the
list of students, or list of teachers based upon the parameter value.
This is done by calling the Print(base[]) with the student[] or
teacher[] based upon the bool.
namespace BaseClass
{
class School
{
List<Teacher> staff = new List<Teacher>();
List<Student> students = new List<Student>();
public Student Students
{
get
{
students.Count();
return Students;
}
}
public Teacher Staff
{
get
{
if(Staff.EnumProp == Status.Employeed)
{
staff.Count();
}
return Staff;
}
}
public void Add(Teacher t1, Student s1) //not sure if this is correct or
//what to do in this method??
{
staff.Add(t1);
students.Add(s1);
//i also need help in the following methods. i am not sure what needs to be put
//in the parameter of the method, based on the instructions.

Based on requirement 1, you'd have to Add(Base c) and determine the collection to add to from there. e.g. (c is Teacher ? staff : students).Add(c). Normally such a class would have overloads (Add(Teacher) and Add(Student)) separately as well to be able to add directly.
public void Add(Base c)
{
if(c is Teacher)
staff.Add((Teacher)c);
else
students.Add((Student)c);
}
2 depends on the output type. With assignments outputting to the console is often enough, so you can use something like
void Print(params Base[] peeps)
{
foreach(var c in peeps)
c.Print();
}
No matter how Print is implemented, step 3 is actually very easy. You can just call your Print(Base[]) as stated in the requirements. To get that array, you have to determine which collection to use, just as in req. 1. (it does sound like 2 separate collections are wanted, otherwise a single collection could be used where Base exposes the role of the person).
public void Print(bool students = true)
{
if(students)
Print(this.students.ToArray());
else
Print(staff.ToArray());
}
PS, as mentioned in the comments the Students and Staff properties seem to expose some behavior that could be changed, but since that outside the scope of the question, won't go there unless you want us to ;)

Add(base) - Takes a teacher/student object and adds it to the appropriate collection.
For adding you can have two methods with same name but different signature. they are called method overloads. Compiler can distinguish between them by looking at the parameters they take.
These methods are both defined in base method. but better design would be to put each method in its appropriate class. (i.e Teacher and Student class)
public void Add(Teacher teacher)
{
staff.Add(teacher);
}
public void Add(Student student)
{
students.Add(student);
}
Print(base[]) - Private method that takes an array of your base class object and prints all the elements of the array.
If i understood correctly you want to print all elements of student or teacher. thats all?
In your base class you can have private method that prints array.
private void Print(Base[] array)
{
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine(array[i].ToString());
}
}
It is better to override ToString method for both Student and Teacher class. for example this method is required in both classes.
public override string ToString() // write this method in both student and teacher classes.
{
return string.Format("Name : {0} , Age : {1}",studentName,studentAge ); // return optional information of student instance.
}
3 Print(bool students = true) - Public method that prints out the list of students, or list of teachers based upon the parameter value. This is done by calling the Print(base[]) with the student[] or teacher[] based upon the bool.
You just need a simple check.
public void Print(bool students = true)
{
if(students)
Print(Students.ToArray());
else
Print(Staff.ToArray());
}
This only works if its inside Base class behind Print(base[]). Otherwise Print(base[]) have to be protected.
A better design would be to add each print method in child classes separately.
In your get and set method what you are doing is really useless.
Count() is a linq method that counts and gives you the length of list. you can use the property of list itself. Count(without parenthesis) which directly gives you the length of list.
Also you dont store the result anywhere so thats why i said its useless. You may want to store the total count. then you can do this.
public int TotalCount
{
get { return staff.Count + students.Count; }
}

Related

Is there a way of storing an object's position in a C# List INSIDE the object?

It should be noted that it's possible for each objects' fields to be indistinguishable from one another within the list and the best way to differentiate them is by ID. It would be extremely helpful if an object's ID could also be its Index in that list.
//...
receiveData(ClassA obj2Add) {
maplist.Insert(0, obj2Add); //Defined as a Maplist, which extends List<ClassA>, assume with no other fields of relevance
Console.WriteLine(obj2Add.Index); //Should display zero.
}
class ClassA {
string mapname {get;set;}
int Index; //Would reference this ClassA's position in maplist.
}
Is there anything I can add to ClassA or the Maplist class to fulfill this goal?
It is possible only if your ClassA ID starts from 0 and then you can do something like:
receiveData(ClassA obj2Add) {
maplist.Insert(0, obj2Add);
maplist=maplist.OrderBy(o=> o.Index).ToList();
Console.WriteLine(obj2Add.Index);
}
Why do you need that anyway? I would guess that you want to select the element by maplist[id]
If this is the case, then I would suggest using
maplis.FirstOrDefault(f=>f.Index==id);

How to sort a List<> that contains derived class objects, by derived class method

I have a double problem here. I need to sort a List<> that I know contains objects of a derived class to the class that the list was declared to contain originally. AND, I need to sort by the return value from a method in that derived class, which takes a parameter. Keep in mind that I already know the List contains objects all of the derived class type.
I've created some sample code here to demonstrate the question since the real code cannot be shared publicly. Note, I have no control over the base conditions here (i.e. the fact that the List<> collection's declared contents are the parent class and that it contains objects of the derived class, which contains a method that takes an argument and returns the values that I need to sort the collection by). So, I doubt I'd be able to use any suggestion that requires changes there. What I think I need is a way to specify (cast?) what is really in the List so I can access the method defined there. But I'm open to other thoughts for sure. Otherwise I'm left with a traditional bubble sort. Thanks.
public class Component
{
public int X;
public int Y;
}
public class ComponentList : List<Component>
{
// Other members that deal with Components, generically
}
public class Fence : Component
{
public int Distance(int FromX, int FromY)
{
int returnValue = 0;
// Caluclate distance...
return returnValue;
}
}
public class Yard : Component
{
// Yada yada yada
}
public class MyCode
{
public List<Component> MyFences;
public MyCode(List<Component> Fences, int FromX, int FromY)
{
// Sort the fences by their distance from specified X,Y
Fences.Sort((A as Fence, B as Fence) => A.Distance(FromX, FromY).CompareTo(B.Distance(FromX, FromY)));
// Or
List<Fence> sortedFences = MyFences.OrderBy(A => A.Distance(FromX, FromY)).ToList();
// Or ???
}
}
Use the Enumerable.Cast<Fence> extension method to transform your IEnumerable<Component> to IEnumerable<Fence>. Then I'd use your second approach (the OrderBy approach) to sort it, but that's my preference.
List<Fence> sortedFences = MyFences.Cast<Fence>().OrderBy(A => A.Distance(FromX, FromY)).ToList();
This approach will throw if there is an object in MyFences that can't be cast to Fence. If you expect that the code should only be passed Fences, this might be what you want. If, instead, you want to skip over non-Fence members, you can use:
List<Fence> sortedFences = MyFences.OfType<Fence>().OrderBy(A => A.Distance(FromX, FromY)).ToList();

Matching specific entries in lists

Currently I'm trying to write a CSV exporter utility for work to help speed up the process of creating work orders for our supervisors. On paper it's quite a simple concept, import the CSV containing our part information and our current production requirements. The columns of the CSV are being split into separate lists. I'm trying to create a button that will allow the user to automatically set the quantity based on the part number.
The way I'm currently thinking about doing this is by grabbing the specific entry on the list's 'spot' (can't think of a better term).
Example:
Dinosaur List
1. T-Rex
2. Triceratops
3. Allosaurus
Diet List
1. Carnivore
2. Herbivore
3. Carnivore
If my user selected Allosaurus, I would want a value returned of 3, and then I would use that to grab the right entry from my second list, in this case, Carnivore.
I'm not sure exactly how I would go about doing this, and any help or direction would be greatly appreciated.
You should really use Object-Oriented programming in this case.
If I were you, I'd declare a class Dinosaur, and make subclasses for each type of dinosaur. In the super class (Dinosaur), put an abstract property of type DinosaurDiet to force subclasses to implement this property. Here's a bit of code to explain what I'm saying:
enum DinosaurDiet //The enumeration for the types of diet
{
Carnivore,
Herbivore
}
abstract class Dinosaur //abstract meaning it can't be instanciated, and only serves as a superclass
{
public abstract DinosaurDiet Diet { get; }
}
class TRex : Dinosaur
{
public override DinosaurDiet Diet { get { return DinosaurDiet.Carnivore; } }
}
class Triceratop : Dinosaur
{
public override DinosaurDiet Diet { get { return DinosaurDiet.Herbivore; } }
}
class Allosaurus : Dinosaur
{
public override DinosaurDiet Diet { get { return DinosaurDiet.Carnivore; } }
}
Once you have all that, you can make a list of them and get them using an index. Here's how:
List<Dinosaur> dinos = new List<Dinosaur>();
dinos.Add(new TRex());
dinos.Add(new Triceratop());
dinos.Add(new Allosaurus());
//Get the 2nd dinosaur from the list (0-based)
int index = 1;
Dinosaur d = dinos[index];
Make sure to test index >= 0 && index < dinos.Count to avoid an exception when trying to get an element at an out-of-bound index.

passing an instance into a method in c#

so ive been doing this assignment all night now and I think ive gone completely wrong on one part. this is the section im stuck on:
TableOrder class will carry two methods for adding items from the menu:
AddFood(), AddDrink(). Each method will pass in a prepared instance of
either the FoodItem or DrinkItem class you previously created. It is expected that the order system will maintain a separate collection
of drinks from food given that we will be passing the drinks orders to
bar staff and likewise food orders to the kitchen.
I have previously created two classes to for FoodItem and DrinkItem but am struggling to grasp the concept of what the question is asking. Please help!
hopefully somebody can explain what it is i am doin wrong. this is the code i have so far...
List<DrinkItem> DrinkMenu = new List<DrinkItem>();
public DrinkItem AddDrink(DrinkItem drinkItem)
{
return drinkItem;
}
public List<DrinkItem> OrderedDrink
{
get
{
return DrinkMenu;
}
}
the next section is as follows:
The TableOrder class provides two separate properties given below, each of which returns a copy of the stored items. Each are expected to return an instance of the List class where T is the appropriate class. It is not expected that I can set these food and drink using these properties.
a. OrderedFood
b. OrderedDrink.
i have ammended the first section and it works, but it has now given me errors on my 2nd part... any ideas as to why this might have happened?
I am going to try to give you some ideas.
First of all you need to have a TableOrder class
public class TableOrder
{
}
Responsibility of the class is: class will carry two methods for adding items from the menu
So, you create two methods in the class who will add things to the order list:
public void AddFood()
{
}
public void AddDrink()
{
}
You also need order list and according to the requirement you need two order lists one for food and another for drink. So, you put two fields in the class like,
private List<FoodItem> FoodOrders = new List<FoodItem>();
private List<DrinkItem> DrinkOrders = new List<DrinkItem>();
In the method you just pass items and add them to this list
public void AddFood(FoodItem fo)
{
FoodOrders.Add(fo);
}
public void AddDrink(DrinkItem do)
{
DrinkOrders.Add(do);
}
And while you are using TableOrder you just need to call these methods to add orders like,
tableOrder.AddDrink(drinkItem);
As i understand this the AddDrink Method should add the Drink to the OrderedDrink List eachtime a Drink is ordered:
public DrinkItem AddDrink(DrinkItem drinkItem)
{
OrderedDrink.Add(drinkItem);
return drinkItem;
}
And if the return value is not needed you may consider declaring the Method as void.
Important would also be to empty the OrderedDrink List eachtime its passed to the kitchen.
The question is asking you to write a class TableOrder which contains two collections. One for storing the ordered DrinkItemss and one for storing the ordered FoodItems. This class should provide two methods:
AddDrink which gets passed a DrinkItem and adds it to the other drinks stored in your collection
AddFood which gets passed a FoodItem and adds it to the collection of ordered foods
In general a method which only returns its parameter without doing anything else like you have written for AddDrink is completely useless so this is an quick and easy check if what you wrote can be right.

passing different objects of same base class to method

Basically, I would like to create a Method, that takes a base-class as a parameter, and can be used "generic" for derived classes
ef-code-first classes:
the base class
public abstract class BaseClass
{
public int Id { get; set; }
public string Name { get; set; }
}
derived classes:
public class DerivedA:BaseClass
{
public string AValue {get;set;}
...more specific fields
}
public class DerivedB:BaseClass
{
public string BValue {get;set;}
..... more specific fields
}
I call a "generic Method" with these slightly different objects:
System.Data.Entity.DbSet<DerivedA> _dA....
System.Data.Entity.DbSet<DerivedB> _dB....
genericMethod(_dA.Where(a => a.Name.StartsWith("a name")))); //<-contains records
genericMethod(_dB.Where(a => a.Id==5)); //<---- contains records
Both "Where..." contain records in debug (after clicking on Enumerate)
now the method:
public string genericMethod(<IQueryable>BaseClass _myClass)
{
foreach (BaseClass c in _myClass) // <-------class is empty - no records
{
// do something usefull...
}
return someResult
}
But no records are contained, when inside the method.
Is it possible, what I am trying to do...?
Does it make sense?
There are no design-time or compile-time or runtime errors, but the passed object contains no records when passed to the method, but it contained records in the calling statement.
What did I do wrong?
Is there a better approach? -
I need this Method, for manipulation of more than two (maybe ten) derived classes, and therefor I want it "generic".
Thank you!
When faced with something like this, I like to simplify my code.
I would try removing the _dA.Where(a => a.Name.StartsWith("a name")) and _dB.Where(a => a.Id==5) from the method call and put them into variables first (and then pass the variable into the method).
This will allow you to better inspect your code and perhaps shed light on the problem.
add .ToList() to materialize the query before you pass it to the method:
genericMethod(_dA.Where(a => a.Name.StartsWith("a name"))).ToList());
Otherwise you're not really passing the result of the query, you're just passing a query that needs to be evaluated first. ToList() will evaluate it for you. When you look in the debugger watch, it's basically evaluating it for you on the fly, that's why you see rows returned.
After that, change your method to deal with IList instead of IQueryable.

Categories