C# Foreach Loop Issue - c#

I was just making this program to experiment with lists and such, and I was curious as to why in the foreach loop the Object always shows up as the "Minecraft" Wish object. Is it because it was the last Wish object to be created? And how can I fix it, so all 3 Wish objects which have been declared show up?
Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Wish iPod = new Wish("iPod", "Various", 299.00);
Wish Phone = new Wish("New Phone", "Various", 00.00);
Wish Minecraft = new Wish("Minecraft Account", "www.minecraft.net", 30.00);
List<Wish> Wishlist = new List<Wish>();
Wishlist.Add(Phone);
Wishlist.Add(iPod);
Wishlist.Add(Minecraft);
Console.WriteLine("Toby's Wishlist");
Console.WriteLine("If cost is 00.00, the Wish's cost varies.");
Console.WriteLine(" ");
foreach (Wish wish in Wishlist)
{
Console.WriteLine("---Wish---");
Console.WriteLine("Name: {0}", wish.getName());
Console.WriteLine("Store: {0}", wish.getStore());
Console.WriteLine("Cost: ${0}", wish.getCost().ToString());
Console.WriteLine("----------");
Console.WriteLine(" ");
}
Console.ReadLine();
}
}
public class Wish
{
static string Name, Store;
static double ApproxCost;
public Wish(string name, string store, double approxCost)
{
Name = name;
Store = store;
ApproxCost = approxCost;
}
public string getName()
{
return Name;
}
public string getStore()
{
return Store;
}
public double getCost()
{
return ApproxCost;
}
}
}

Remove static from Wish members declaration
static means that the data will be shared across all the instances. So static members are also so called class variables. While not static members - are object variables.

It's because in class Wish you declared Name, Score, and ApproxCost as static.

Related

how to print properties of object in list?

i am a begginer in c# .
my problem is that i want to create a list of objects that i can add objects dynamically and then print their properties(i want to go to every object that i want and print only his properties).
i looked around the internet and didn't find a good answer that will help me understand how to to do it correctly.
i added a try...catch to understand the problem but the explantation i got is that i didn't add instance to print his properties even that i totaly did it.
i am really lost so any help would be appreciated.
my code :
class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using APPcLASS_2;
using System.Collections;
namespace EmployeesBooks
{
public class EMpLOYcLaSS
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int PhoneNumber { get; set; }
public string Adress { get; set; }
public int Days { get; set; }
public int Mounths { get; set; }
public int Years { get; set; }
}
}
main program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using APPcLASS_2;
using EmployeesBooks;
namespace EmployeesBooks
{
class Program
{
static void Main(string[] args)
{
EMpLOYcLaSS Employ = new EMpLOYcLaSS();
List<EMpLOYcLaSS> ListOfObjects = new List<EMpLOYcLaSS>();
string FirstNameVar, LastNameVar, AdressVar;
int PhoneNumberVar, DayVar, MounthVar, YearVar;
while(true)
{
Console.Clear();
Console.WriteLine("Enter your choise:");
Console.WriteLine("1-Add an employee");
Console.WriteLine("2-Earase employee");
Console.WriteLine("3-Show reports");
var choise=int.Parse(Console.ReadLine());
switch(choise)
{
case 1:
Console.WriteLine("Enter First Name:",Employ.FirstName);
FirstNameVar = Console.ReadLine();
Employ.FirstName = FirstNameVar;
Console.WriteLine("Enter Last Name:");
LastNameVar = Console.ReadLine();
Employ.LastName = LastNameVar;
Console.WriteLine("Enter Phone Number:");
PhoneNumberVar =int.Parse(Console.ReadLine());
Employ.PhoneNumber = PhoneNumberVar;
Console.WriteLine("Enter Address:");
AdressVar = Console.ReadLine();
Employ.Adress = AdressVar;
Console.WriteLine("Enter Birthday:");
Console.WriteLine("Day:");
DayVar =int.Parse(Console.ReadLine());
Employ.Days = DayVar;
Console.WriteLine("Mounth:");
MounthVar = int.Parse(Console.ReadLine());
Employ.Mounths = MounthVar;
Console.WriteLine("Year:");
YearVar = int.Parse(Console.ReadLine());
Employ.Years = YearVar;
ListOfObjects.Add(new EMpLOYcLaSS());
break;
case 3:
try
{
Console.WriteLine("enter a number of employee:(1,2,3,4...)");
var EmployeeNumberForPrinting = int.Parse(Console.ReadLine());
if (ListOfObjects[EmployeeNumberForPrinting] != null)
Console.WriteLine("{0}", ListOfObjects[EmployeeNumberForPrinting].FirstName.ToString());
else
Console.WriteLine("Don't Exist!");
Console.WriteLine("Press any key to proceed");
Console.ReadKey();
break;
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
break;
}
}
}
}
}
}
Well first of all you don't add the employee into the list, you add a new one.
Change
ListOfObjects.Add(new EMpLOYcLaSS());
To
ListOfObjects.Add(Employ);
That will add the employee you created into the list, now to print each employee's name for example.
foreach(var e in ListOfObjects)
{
Console.WriteLine(e.FirstName + " " + e.LastName);
}
Obviously you can add more properties as you wish, this simply goes through all the objects and prints each of their names. Your code to print a predetermined employee should work now, just remove ToString() as it's already a string. Just a note, remember 0 is the first index in a list. I recommend for usability add one to EmployeeNumberForPrinting due to this, your decision.

Calling a method that expects an array of objects

I'm learning C# and have written a console program to save an an array of high scores to a file. Although the program works, how I have got it to work is making me feel uneasy and feels more of a hack than a solution so I was looking for guidance on how I should have written it.
What I am currently doing within the Main method is:
Declaring an array of highscore objects
Initialising them
Assigning some values to the array.
I am happy with what I have done up until now, it's the following two steps that make me uneasy
I then declare another HighScore object
I use this object to pass the array of highscores to the SaveHighScores method.
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace HighScore
{
class HighScore
{
public string Name { get; set; }
public int Score { get; set; }
public void SaveHighScores(HighScore[] highScores)
{
string allHighScoresText = "";
foreach (HighScore score in highScores)
{
allHighScoresText += $"{score.Name},{score.Score}" + Environment.NewLine;
}
File.WriteAllText("C:/Temp/highscores.csv", allHighScoresText);
}
static void Main(string[] args)
{
HighScore[] highScore = new HighScore[2];
for (int i = 0; i < highScore.Length; i++)
{
highScore[i] = new HighScore();
}
highScore[0].Name = "A";
highScore[0].Score = 100;
highScore[1].Name = "B";
highScore[1].Score = 200;
// are the following two lines correct or am I missing something?
HighScore hs = new HighScore();
hs.SaveHighScores(highScore);
}
}
}
Make SaveHighScores static and you won't need an instance of HighScore to call it. (You can call it directly as HighScore.SaveHighScores())
I prefer to split the representation of your data from the actions that you perform on this data. So I would go for two classes, one for the Data and one for the Save/Load and other business logic
public class HighScore
{
public string Name { get; set; }
public int Score { get; set; }
}
// This class handles the core work to persist your data on the storage medium
// The class is static so you don't need to declare instances and use directly the methods available.
public static class Repo_HighScore
{
// For simplicity, no error Handling but, for a robust implementation,
// error handling is required
public static bool SaveHighScores(HighScore[] highScores)
{
StringBuilder allHighScoresText = new StringBuilder();
foreach (HighScore score in highScores)
allHighScoresText.AppendLine($"{score.Name},{score.Score}");
File.WriteAllText("C:/Temp/highscores.csv", allHighScoresText.ToString());
}
public static HighScore[] LoadHighScores()
{
List<HighScore> hs = new List<HighScore>();
foreach(string line in File.ReadLines("C:/Temp/highscores.csv"))
{
string[] parts = line.Split(',');
HighScore temp = new HighScore()
{ Name = parts[0], Score = Convert.ToInt32(parts[1])};
hs.Add(temp);
}
return hs.ToArray();
}
}

confused about Passing by reference and passing by value in c#

i am a new programmer here. I have the following code. I passed the object by value, but when i printed the results, i got this
elf attacked orc for 20 damage!
Current Health for orc is 80
elf attacked orc for 20 damage!
Current Health for orc is 80
this got me confused about passing by reference because I did not expect the health in the main to be 80 since i passed the object by value. Can someone explain how the result for health in the program main function was 80 instead of 100?
//MAIN class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace passingTest
{
class Program
{
static void Main(string[] args)
{
// Enemy Objects
Enemy elf = new Enemy("elf", 100, 1, 20);
Enemy orc = new Enemy("orc", 100, 1, 20);
elf.Attack(orc);
Console.WriteLine("{0} attacked {1} for {2} damage!", elf.Nm, orc.Nm, elf.Wpn);
Console.WriteLine("Current Health for {0} is {1}", orc.Nm, orc.Hlth);
Console.ReadLine();
}
}
}
// Enemy Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace passingTest
{
class Enemy
{
// variables
string nm = "";
int hlth = 0;
int lvl = 0;
int wpn = 0;
public string Nm
{
get { return nm; }
set { nm = value; }
}
public int Wpn
{
get { return wpn; }
set { wpn = value; }
}
public int Hlth
{
get { return hlth; }
set { hlth = value; }
}
public Enemy(string name, int health, int level, int weapon)
{
nm = name;
hlth = health;
lvl = level;
wpn = weapon;
}
public void Attack(Enemy rival){
rival.hlth -= this.wpn;
Console.WriteLine("{0} attacked {1} for {2} damage!", this.nm, rival.nm, this.wpn);
Console.WriteLine("Current Health for {0} is {1}", rival.nm, rival.hlth);
}
}
}
In C#/.NET, whether an object is passed by reference or by value is determined by the type of the object. If the object is a reference type (i.e. it is declared with class), it is passed by reference. If the object is a value type (i.e. it is declared with struct) it is passed by value.
If you change the declaration of Enemy to
struct Enemy
you will see pass-by-value semantics.
In C# Classes are considered reference types. A reference type is a type which has as its value a reference to the appropriate data rather than the data itself. For instance, consider the following code:
Here;s a link with more information on the subject: http://jonskeet.uk/csharp/parameters.html

Adding objects to an array in the constructor

I am making a simple c# web service that takes in a name and returns the corresponding phone number.
So I created a contact class with a name field and a number field
Here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PhoneService
{
class Contact
{
String name;
int number;
//constructor to make new contact
public Contact(String name, int number)
{
this.name = name;
this.number = number;
}
}
}
And here is my web service class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PhoneService
{
class PhoneBook : IPhoneBook
{
Contact[] contactList = new Contact[4];
//constructor
public PhoneBook ()
{
contactList[0] = new Contact("Mary Jones", 1800252525);
contactList[1] = new Contact("Bob Smith", 1800343434);
contactList[2] = new Contact("Martin Dunne", 1800797979);
contactList[3] = new Contact("Sarah Mitchel", 1800898989);
}
//method to look up name
public string lookUpNumberByName(string name)
{
//variable to hold name entered
String nameEntered = name; ;
/**
code to compare the name entered with the
the names of the contact objects.
If the name is a match with a contact name then return
the associated number
**/
//return number corresponding to the name
return null;
}
}
}
So I am trying to make 4 simple contact objects stored in an array then when I enter a name I can check if it matches one of them and return the relevant phone number.
The problem is with the constructor
My assignment says-
"Have the service maintain a list of names and phone numbers in a collection in memory which is initialised in the constructor for the service class."
So I don't know what parts I should have in the constructor and what should be outside in the main class.Hopefully someone can let me know the best way I can go ahead with this.
Thanks in advance
UPDATE
I have redone my code and made it a bit more simple by removing the contact class.
Here it is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PhoneService
{
class PhoneBook : IPhoneBook
{
static String[] nameList = new String[4];
static String[] numberList = new String[4];
//constructor
public PhoneBook()
{
nameList[0] = ("Mary Jones");
nameList[1] = ("Bob Smith");
nameList[2] = ("Martin Dunne");
nameList[3] = ("Martin Dunne");
numberList[0] = ("1800252525");
numberList[1] = ("1800343434");
numberList[2] = ("1800797979");
numberList[3] = ("1800898989");
}
//method to look up name
public String lookUpNumberByName(String name)
{
try
{
if (string.Equals(name, nameList[0], StringComparison.CurrentCultureIgnoreCase))
{
return numberList[0];
}
if (string.Equals(name, nameList[1], StringComparison.CurrentCultureIgnoreCase))
{
return numberList[1];
}
if (string.Equals(name, nameList[2], StringComparison.CurrentCultureIgnoreCase))
{
return numberList[2];
}
if (string.Equals(name, nameList[3], StringComparison.CurrentCultureIgnoreCase))
{
return numberList[3];
}
}
catch (System.Exception)
{
return ("That name is not found");
}
}//end of lookUpNumberByName method
}//end of class phonebook
}// end of phoneservice
My lookUpNumberByName method is getting an error saying not all code paths return a value
You're basically asking about encapsulation. Generally, you want to think of what parts of the class you want to expose kind of like an engineer thinks about what controls of a car to expose to a driver. Basically, if no one on the outside will need to use this property of this method, don't expose it, just leave it be.
What your assignment is effectively asking you to do is not to expose a property but to set a contact list via a service constructor. So if you need to set your contact list, shouldn't you just pass a contact list into the constructor for your phone book? And remember that you can have multiple constructors and if you don't specify one that takes no arguments, you won't be able to simply declare an instance of that class without passing arguments.
You mean something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PhoneService
{
class PhoneBook : IPhoneBook
{
private static List<Contact> _contactList = new List<Contact>();
//constructor
public PhoneBook (List<Contact> contactList)
{
_contactList = contactList;
}
public PhoneBooks()
{
}
}
}
you can use it like this
using System;
class Program
{
static void Main()
{
var contactList = new List<Contact>();
contactList.Add(new Contact("Mary Jones", 1800252525));
contactList.Add(new Contact("Bob Smith", 1800343434));
contactList.Add(new Contact("Martin Dunne", 1800797979));
contactList.Add(new Contact("Sarah Mitchel", 1800898989));
var phoneBook = new PhoneBook(contactList);
}
}

How to use BinaryReader and correctly input data into file?

I am working on my homework assignment and I am completely stuck! What I am trying to do is to use already defined input and save it to the file by using saveDataTo() method and read the input by using readDataFrom() method.
I am stuck on the first part. I am not sure if I have to initialize the data in Program.cs file first?
I don't know and I am stuck. Here is code and hope for some tips how I can accomplish this.
-- EDIT --
I can add instructions for purpose of both saveDataTo() and readDataFrom() methods:
The saveDataTo( ) method takes a parameter of BinaryWriter. The method
writes the values of all 5 properties of an book object to a file
stream associated with the writer (the association is done in the
Main( ) method of Program class). There is no need to open and close
the file stream and binary writer inside this method.
The readDataFrom( ) method takes a parameter of BinaryReader. The
method reads the values of all five properties of the Book object from
a file stream associated with the reader (the association is done in
the Main( ) method of Program class). There is no need to open and
close the file stream and binary reader inside this method.
So that gives me a clue that I should use and assign the properties to be saved in the file there?
-- EDIT --
Updated the code there. I do have a problem with content that is being saved into the file. I am not being showed the price. Why is that?
ff.APublisherNameTitle FirstNameLastName
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Lab_7
{
class Program
{
private const string FILE_NAME = "lab07.dat";
static void Main(string[] args)
{
//char ask;
/*
do
{
Console.Write("Enter Book Title: ");
publication.Title = Console.ReadLine();
Console.Write("Enter Author's First Name: ");
book.AuthorFirstName = Console.ReadLine();
Console.Write("Enter Author's Last Name: ");
book.AuthorLastName = Console.ReadLine();
Console.Write("Enter Publisher's Name: ");
publication.PublisherName = Console.ReadLine();
Console.Write("Enter Book Price: $");
publication.Price = float.Parse(Console.ReadLine());
Console.Write("Would like to enter another book? [Y or N] ");
ask = char.Parse(Console.ReadLine().ToUpper());
}
while (ask == char.Parse("Y"));
*/
Book book = new Book();
book.Price = 10.9F;
book.Title = "Title";
book.PublisherName = "PublisherName";
book.AuthorFirstName = "FirstName";
book.AuthorLastName = "LastName";
FileStream fileStream = new FileStream(FILE_NAME, FileMode.OpenOrCreate);
BinaryWriter write = new BinaryWriter(fileStream);
book.saveDataTo(write);
write.Close();
fileStream = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
BinaryReader read = new BinaryReader(fileStream);
book.readDataFrom(read);
read.Close();
}
}
}
Publication.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Lab_7
{
class Publication
{
private float price;
private string publisherName, title;
public float Price
{
get
{
return price;
}
set
{
price = value;
}
}
public string PublisherName
{
get
{
return publisherName;
}
set
{
publisherName = value;
}
}
public string Title
{
get
{
return title;
}
set
{
title = value;
}
}
public void display()
{
Console.WriteLine("{0}\n{1}\n{2}", title, publisherName, price);
}
}
}
Book.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Lab_7
{
class Book : Publication
{
private string authorFirstName, authorLastName;
public string AuthorFirstName
{
get
{
return authorFirstName;
}
set
{
authorFirstName = value;
}
}
public string AuthorLastName
{
get
{
return authorLastName;
}
set
{
authorLastName = value;
}
}
public new void display()
{
}
public string getAuthorName()
{
return authorFirstName + " " + authorLastName;
}
public void readDataFrom(BinaryReader r)
{
Price = r.ReadInt32();
PublisherName = r.ReadString();
Title = r.ReadString();
authorFirstName = r.ReadString();
authorLastName = r.ReadString();
}
public void saveDataTo(BinaryWriter w)
{
w.Write(base.Price);
w.Write(base.PublisherName);
w.Write(base.Title);
w.Write(AuthorFirstName);
w.Write(AuthorLastName);
}
}
}
Regards.
HelpNeeder.
You're asking whether to define the values in Program.cs or Book.cs, right? Well, it is fine to define the values in Program.cs, you just need to make sure all the values are given before writing the data.
So, since the function takes a BinaryWriter parameter that is supposedly initialized beforehand, this should work:
public void saveDataTo(BinaryWriter w)
{
w.Write(getAuthorName());
//etc...
}
But, just remember that you do need to define all the info somewhere (anywhere) before calling save data.
You assign your parameters to 2 different objects, see:
Publication publication = new Publication();
Book book = new Book();
Both are individual instances residing in memory.
You either have to refer the publication to the book like:
Book book = new Book();
Publication publication = (Publication)book;
or just assign the values currently assigned to the publication directly to the book so:
publication.PublisherName = "PublisherName";
becomes
book.PublisherName = "PublisherName";
Apart from that, you're working in C#, not Java. By convention its normal to start your methods with a Capital (Pascal Case)
EDIT
Your now shown the price when reaidng since you write it as a floating field (or double, cant see the definition) and read it as an integer.
Change from r.ReadInt32(); to r.ReadDouble(); or r.ReadSingle()

Categories