passing an instance into a method in c# - 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.

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

Taking an object and adding it to the appropritae collection

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

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.

Pros/Cons on Lists with subsidiary objects

I'm again in the position to figure a way out to handle lists with subsidiary objects on our business objects.
Actually, our code often looks like this:
public class Object
{
private List<SubsidiaryObject> subsidiaryObjects = null;
public List<SubsidiaryObject> SubsidiaryObjects
{
get
{
if (this.subsidiaryObjects == null)
{
this.subsidiaryObjects = DBClass.LoadListFromDatabase();
}
return this.subsidiaryObjects;
}
set
{
this.subsidiaryObjects = value;
}
}
}
The Con on this:
The property is referenced in presentation layer and used for DataBinding. Releasing the reference to the actual list and replacing it with a new one will end in an referenced list in the GUI that does not have anything left with the list on the object.
The Pro on this:
Easy way of reloading the list (just set the reference to null and then get it again).
I developed another class that uses the following pattern:
public class Object2
{
private readonly List<SubsidiaryObject> subsidiaryObjects = new List<SubsidiaryObject>();
public List<SubsidiaryObject> SubsidiaryObjects
{
get
{
return this.subsidiaryObjects;
}
}
public void ReloadSubsidiaryObjects()
{
this.SubsidiaryObjects.Clear();
this.SubsidiaryObjects.AddRange(DBClass.LoadListFromDatabase());
}
}
Pro on this:
Reference is continous.
The Con on this:
Reloading the list is more difficult, since it just cannot be replaced, but must be cleared/filled with reloaded items.
What is your preferred way, for what situations?
What do you see as Pro/Con for either of these to patterns?
Since this is only a general question, not for a specific problem, every answer is welcome.
Do you need the caller to be able to modify the list? If not you should consider returning IEnumerable<T> or ReadOnlyCollection instead. And even if you do, you will probably be better off making cover versions for Add/Remove so you can intercept modifications. Handing a reference to internal state is not a good idea IMO.
A third option would be to go with option 2, but to create a new instance of the Object2 type each time you need to repopulate the list. Without additional context for the question, that is the option I would select, but there may be reasons why you would want to hold on to the original instance.

C#: Encapsulation of for example collections

I am wondering which one of these would be considered the cleanest or best to use and why.
One of them exposes the a list of passengers, which let the user add and remove etc. The other hides the list and only let the user enumerate them and add using a special method.
Example 1
class Bus
{
public IEnumerable<Person> Passengers { get { return passengers; } }
private List<Passengers> passengers;
public Bus()
{
passengers = new List<Passenger>();
}
public void AddPassenger(Passenger passenger)
{
passengers.Add(passenger);
}
}
var bus = new Bus1();
bus.AddPassenger(new Passenger());
foreach(var passenger in bus.Passengers)
Console.WriteLine(passenger);
Example 2
class Bus
{
public List<Person> Passengers { get; private set; }
public Bus()
{
Passengers = new List<Passenger>();
}
}
var bus = new Bus();
bus.Passengers.Add(new Passenger());
foreach(var passenger in bus.Passengers)
Console.WriteLine(passenger);
The first class I would say is better encapsulated. And in this exact case, that might be the better approach (since you should probably make sure it's space left on the bus, etc.). But I guess there might be cases where the second class may be useful as well? Like if the class doesn't really care what happens to that list as long as it has one. What do you think?
In example one, it is possible to mutate your collection.
Consider the following:
var passengers = (List<Passenger>)bus.Passengers;
// Now I have control of the list!
passengers.Add(...);
passengers.Remove(...);
To fix this, you might consider something like this:
class Bus
{
private List<Passenger> passengers;
// Never expose the original collection
public IEnumerable<Passenger> Passengers
{
get { return passengers.Select(p => p); }
}
// Or expose the original collection as read only
public ReadOnlyCollection<Passenger> ReadOnlyPassengers
{
get { return passengers.AsReadOnly(); }
}
public void AddPassenger(Passenger passenger)
{
passengers.Add(passenger);
}
}
In most cases I would consider example 2 to be acceptable provided that the underlying type was extensible and/or exposed some form of onAdded/onRemoved events so that your internal class can respond to any changes to the collection.
In this case List<T> isn't suitable as there is no way for the class to know if something has been added. Instead you should use a Collection because the Collection<T> class has several virtual members (Insert,Remove,Set,Clear) that can be overridden and event triggers added to notify the wrapping class.
(You do also have to be aware that users of the class can modify the items in the list/collection without the parent class knowing about it, so make sure that you don't rely on the items being unchanged - unless they are immutable obviously - or you can provide onChanged style events if you need to.)
Run your respective examples through FxCop and that should give you a hint about the risks of exposing List<T>
I would say it all comes down to your situation. I would normally go for option 2 as it is the simplest, unless you have a business reason to add tighter controls to it.
Option 2 is the simplest, but that lets other classes to add/remove elements to the collection, which can be dangerous.
I think a good heuristic is to consider what the wrapper methods do. If your AddPassenger (or Remove, or others) method is simply relaying the call to the collection, then I would go for the simpler version. If you have to check the elements before inserting them, then option 1 is basically unavoidable. If you have to keep track of the elements inserted/deleted, you can go either way. With option 2 you have to register events on the collection to get notifications, and with option 1 you have to create wrappers for every operation on the list that you want to use (e.g. if you want Insert as well as Add), so I guess it depends.

Categories