Creating multiple inputs to a ClassList - c#

So I have coded for a while I C# and learned the basics, one thing that always stops me is how I can create a class and then use a list for a user to input values.
I don't know if I'm totally off the chart with this code, the problem is that I don't understand why I can't use my newly created object of the class and add input to it. All help is appreciated
class Program
{
static void Main(string[] args)
{
List<Citizen> listOfCitizens = new List<Citizen>();
for (int i = 0; i < listOfCitizens.Count; i++)
{
Console.WriteLine("Enter Surname for the citizen:");
listOfCitizens.SurName.add = Console.ReadLine();
Console.WriteLine("Enter Lastname for the citizen:");
listOfCitizens.Lastname.add = Console.ReadLine();
Console.WriteLine("Enter age of the citizen:");
listOfCitizens.age.add = int.Parse(Console.ReadLine());
}
Console.WriteLine($"Name {Citizen.SurName} {Citizen.LastName} {Citizen.age}");
Console.Read();
}
}
class Citizen
{
public static string SurName{ get; set; }
public static string LastName{get;set;}
public static int age { get; set; }
}

A list of something is not a something. Just like a basket of apples is not an apple. You don't eat the basket, you eat an item from the basket.
So when you create your list:
List<Citizen> listOfCitizens = new List<Citizen>();
You would then create an item to add to the list:
Citizen someCitizen = new Citizen();
someCitizen.SurName = "Smith";
// etc.
And then add it to the list:
listOfCitizens.Add(someCitizen);
Additionally, your Citizen is a little off. Those properties shouldn't be static. Not sure why you made them that way, but you should remove the static keyword from everything in your Citizen class.

Related

Can I list a number if class instances in an array?

I am just starting out with learning C#, and to practice I am trying to create a hangman game (guess letters of a word).
I created a class WordToGuess and created multiple instances of this class, one for each word.
Now I would like to randomly pick one of these instances to be guessed by the player. I am not sure how to approach this.
I found code to randomly pick an index from an array, which seems to be a good way to do it. But now I don't know what exactly I can do. Can I list instances in an array? And if not, how can I elegantly do it otherwise. I can think of a workaround, but that's not the point of the exercise.
Example of my instance:
WordToGuess duck = new WordToGuess();
duck.numberOfLetters = 4;
duck.theWord = "Duck";
duck.theLetters = new string[] { "d", "u", "c", "k" };
duck.difficulty = "easy";
duck.wordID = "e3";
My random generation attempt (I thought I could just generate the string ID and then address the instance that way, I think I didn't think that through though)
string[] easyWords = new string[] { "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
Random rndE = new Random();
int indexE = rndE.Next(easyWords.Length);
An example with arrays:
class Program
{
static void Main(string[] args)
{
WordToGuess[] wtg = new WordToGuess[10];
wtg[0] = new WordToGuess("Duck", "easy", "e3");
wtg[1] = new WordToGuess("Dog", "easy", "e4");
wtg[2] = new WordToGuess("House", "easy", "e5");
wtg[3] = new WordToGuess("Pneumonoultramicroscopicsilicovolcanoconiosis", "difficult", "e6");
Console.WriteLine();
foreach (var item in wtg)
{
if (item is not null)
{
Console.WriteLine($"{item.wordID}, {item.theWord}, {item.difficulty}, {item.numberOfLetters}");
}
}
Console.WriteLine();
Random r = new Random();
WordToGuess randomWord = wtg[r.Next(0, 3)];
Console.WriteLine($"A random word: {randomWord.wordID}, {randomWord.theWord}, {randomWord.difficulty}, {randomWord.numberOfLetters}");
// this needs: using System.Linq;
randomWord = wtg.Where(x => x is not null).OrderBy(x => r.Next()).First();
Console.WriteLine($"Another random word: {randomWord.wordID}, {randomWord.theWord}, {randomWord.difficulty}, {randomWord.numberOfLetters}");
Console.ReadLine();
}
}
public class WordToGuess
{
public int numberOfLetters { get; set; }
public string theWord { get; set; }
public char[] theLetters { get; set; }
public string difficulty { get; set; }
public string wordID { get; set; }
public WordToGuess()
{}
public WordToGuess(string theWord, string difficulty, string wordID)
{
this.numberOfLetters=theWord.Length;
this.theWord=theWord;
this.theLetters=theWord.ToUpper().ToCharArray();
this.difficulty=difficulty;
this.wordID=wordID;
}
}
output like this:
e3, Duck, easy, 4
e4, Dog, easy, 3
e5, House, easy, 5
e6, Pneumonoultramicroscopicsilicovolcanoconiosis, difficult, 45
A random word: e4, Dog, easy, 3
Another random word: e5, House, easy, 5
The word Pneumo....iosis was found here: https://irisreading.com/10-longest-words-in-the-english-language/
There are many ways to do what you want. Maybe one of the best would be to store the WordToGuess instances in a Dictionary<string, WordToGuess> where the key is that identifier.
But i would also refactor your class, some properties are not needed like the string[] for the letters, since string already implements IEnumerable<char>. I would also make that Diffciculty an enum instead of a string and provide a constructor for WordToGuess that takes the most important properties as input:
public class WordToGuess
{
public enum GuessDifficulty
{
Easy, Medium, Hard
}
public WordToGuess(string word, string id, GuessDifficulty difficulty)
{
TheWord = word;
ID = id;
Difficulty = difficulty;
}
public string ID {get;set;}
public string TheWord {get;set;}
public GuessDifficulty Difficulty {get;set;}
}
Now you can initialize and fill the dictionary in this way:
Dictionary<string, WordToGuess> wordDictionary = new Dictionary<string, WordToGuess>();
WordToGuess duck = new WordToGuess("Duck", "e3", WordToGuess.GuessDifficulty.Easy);
wordDictionary.Add(duck.ID, duck);
// initialize and add more ...
Your random word logic then just tries to find the word with the Id in the dictionary:
string[] easyWords = new string[] { "e1", "e2", "e3", "e4", "e5", "e6", "e7" };
Random rndE = new Random();
int idIndex = rndE.Next(easyWords.Length);
WordToGuess randomWord = wordDictionary.TryGetValue(easyWords[idIndex], out WordToGuess w) ? w : null;
Note that it's null if there is not a word with that random identifier.
Make a List and add all instances to the list. Then use that random index code on the list. In C# we rarely use [] and instead use lists. (Yes you can have object instances in an array)

Calling a variable have user input from a different method

i have fixed the question:
The code is working until it hit the MultyMethod it stop because i have tried to take the output from the SumMethod and do another calculation in the MultyMethod.
So my question is i have tried to use the same input from SumMethod in the MultyMethod but it does not work well i have used all the reference in my mind or i could think of but still it told me : the name "SumMethod" need a reference to call it or you forgetting to use a reference. So how i could use the same input from the SumMethod in the MultyMethod!!
using System;
namespace example
{
class Program
{
public int number1 { set; get; }
public int number2 { set; get; }
public int sum { set; get; }
public int multy { set; get; }
static void Main(string[] args)
{
var value = SumMethod();
var values = MultyMethod();
ResultMethod(value.number1, value.number2, value.sum, values.multy);
}
public static Program SumMethod()
{
var input = new Program();
int i = 0;
Console.WriteLine(" Please Enter your first number: ");
input.number1 = int.Parse(Console.ReadLine());
Console.WriteLine(" Please Enter your second number: ");
input.number2 = int.Parse(Console.ReadLine());
int[] arr = new int[] { input.number1, input.number2 };
do
{
input.sum += arr[i];
i++;
} while (i < 2);
return input;
}
public static Program MultyMethod()
{
var input = new Program();
// here is the issue i am trying to get the input from the previous method instead of asking the user to input the numbers again
// i have tried this
//input.number1 = new input.SumMethod();
// and also have tried to use this reference
//value.SumMethod(); // since the inputs store in this variable but it does not make since to call it this way ><
// i have also tried to use this way
//input.number1 = new SumMethod();
return input;
}
public static void ResultMethod(int number1, int number2, int sum, int multy)
{
Console.WriteLine(" The first number is: ");
Console.WriteLine(number1);
Console.WriteLine(" The second number is: ");
Console.WriteLine(number2);
Console.WriteLine(" The sum of the number is: ");
Console.WriteLine(sum);
Console.WriteLine(" The multiplication of the numbers is: ");
Console.WriteLine(multy);
}
}
}
Okay, your basic problem is that the variable input, which you wish to reference in MultyMethod, is internal to SumMethod. Therefore, MultyMethod can't access it.
You define another variable called input in MultyMethod, but that is NOT the same variable. It's a separate one, the scope of which is just MultyMethod, and can't be accessed outside of it.
So, how to do what you want. I hope you don't mind that I'm also going to make some suggestions about how you could better organize this code.
First, you could define input outside of SumMethod, as a class-level static variable. In that case, it could be accessed by both SumMethod and MultyMethod. The following is a short excerpt (with some lines removed to save space):
class Program
{
public int number1 { set; get; }
public int number2 { set; get; }
public int sum { set; get; }
public int multy { set; get; }
public static Program input = null;
static void Main(string[] args)
{
// etc.
}
public static Program SumMethod()
{
input = new Program();
// rest of the code
return input;
}
public static Program MultyMethod()
{
input = Program.input; // this is a static reference.
// desired multiplication code
return input;
}
Another option would be to parameterize MultyMethod so it takes a Program as a parameter, representing the input:
public static Program MultyMethod(Program input)
{
// You probably don't want to have the same variable have both your sum
// and your multiplication results.
Program newVar = new Program() { number1 = input.number1, number2 = input.number2 };
// Do things with newVar in place of "input"
return newVar;
}
Then you'd change Main to look like this:
var value = SumMethod();
var values = MultyMethod(value);
An even better version would separate getting the input from performing the summing. So you could do this:
static void Main(string[] args)
{
var input = GetInput();
var value = SumMethod(input);
var values = MultyMethod(input);
// do other things
}
Finally, the whole thing would be better if you had separate classes for all three of the following:
The program itself
The input parameters and results
The multiplication and sum methods

C# How to print a list containing textbox and numbericupdown value?

So I am working on this project and am stuck.
I am trying to print a list containing textbox text and numbericupdown values.
This is my class
class Animal
{
public string Species{ get; set; }
public int Size{ get; set; }
public string Eater{get; set;}
public Dier(string species, int size, string eater)
{
this.Species= species;
this.Size= size;
this.Eater= eater;
}
class Program
{
static void Hoofd()
{
Animal animal1= new Animal("Panda", 3, "Herbivore");
Console.WriteLine("animal1 Species = {0} Size = {1} Eater = {2}", animal1.Species, animal1.Size, animal1.Eater);
}
}
}
The output of this code is what I am trying to achieve.
So I have 2 textboxes and 1 numericupdown.
I want to store this information in a animal2 list like this:
int numericUpDownChangeToInt = Convert.ToInt32(numericUpDown1.Value);
Animal animal2 = new Animal(textBox1.Text, numericUpDownChangeToInt, textBox2.Text);
Console.WriteLine(animal2);
And print this information to the console output,
The result that I am getting is: Animalproject.Animal
The result that I would like to get is the input of the textboxes and the numericupdown.
Can anyone help me?
Thanks in advance!
You will have to access the properties of the Animal class in order to print out the values. See below code.
int numericUpDownChangeToInt = 2; //Convert.ToInt32(numericUpDown1.Value);
Animal animal2 = new Animal("Textbox1", numericUpDownChangeToInt, "Textbox2");
Console.WriteLine("Species: "+ animal2.Species + "\nSize: "+ animal2.Size.ToString() + "\nEater: "+ animal2.Eater);

Using a method to initialize

So up until recently I've been initializing all my stuff within the main function, but this makes it (imo) pretty ugly. So I went ahead and thought instead of having me write out the initializing , I'd just have a method to do it for me which would explain itself just by its name (Create.ClassRoom()). So I went ahead and made this class with the method to do it:
class Create
{
public static void ClassRoom()
{
Student Henry = new Student("Henry", 20);
Student Jeff = new Student("Jeff", 18);
Student Jessica = new Student("Jessica", 22);
Teacher MrLopez = new Teacher("Lopez", "Math", 37);
}
which would make main look much nicer:
class Program
{
static void Main(string[] args)
{
Create.ClassRoom();
Console.WriteLine(Henry.age);
}
}
However, it says Henry doesn't exist in the current context. Now I understand this has to do with scope, but I can't seem to think or find a solution to it. Is my idea just not doable or am I missing something? I'd like it to be so that after I do Create.ClassRoom(); it would allow me to interact with whatever is initialized in there.
Yes, you're right. It has to do with the scope. The initialized variables are not accessible outside of the CreateClassRoom() method. You'll have to return an instance of the class room to the calling method.
Refactor your class as follows:
class ClassRoom
{
public List<Student> Students { get; private set; }
public List<Teacher> Teachers { get; private set; }
public ClassRoom()
{
this.Students = new List<Student>();
this.Teachers = new List<Teacher>();
}
}
class Create
{
public static ClassRoom ClassRoom()
{
ClassRoom classRoom = new ClassRoom();
classRoom.Students.Add(new Student("Henry", 20));
classRoom.Students.Add(new Student("Jeff", 18));
classRoom.Students.Add(new Student("Jessica", 22));
classRoom.Teachers.Add(new Teacher("Lopez", "Math", 37));
return classRoom;
}
}
The Create.ClassRoom() method returns an instance of the ClassRoom object, using which you will be able to access the Students and Teachers in the class.
From Main(), you could access the properties as follows:
static void Main(string[] args)
{
var classRoom = Create.ClassRoom();
Console.WriteLine("Students: ");
foreach (var student in classRoom.Students)
{
Console.WriteLine("Name: {0}; Age: {1}", student.Name, student.Age);
}
Console.WriteLine("Teachers: ");
foreach (var teacher in classRoom.Teachers)
{
Console.WriteLine("Name: {0}; Subject: {1}", teacher.Name, teacher.Subject);
}
}
Henry cannot be accessed by main() because it is within the scope of the function ClassRoom(). You need to make it return a Student object or better yet, create a class that has a getter and setter for the variables you want to access.

ArrayList Conceptual Issues

I have tried to add 2 types of objects in an Array List and then have tried to display them but somehow it is not working. Do I need to use 2 Array List objects or how is it going to work?
Error Message:
Unable to cast object of type 'ArrayList_Practice.Student' to type
'ArrayList_Practice.Employees'.
class Program
{
static void Main(string[] args)
{
Student st=null;
Employees emp = null;
ArrayList al = new ArrayList();
Console.WriteLine("Enter Records");
for (int i = 0; i < 2; i++)
{
st = new Student();
Console.WriteLine("Enter roll");
st.roll = int.Parse(Console.ReadLine());
Console.WriteLine("Enter name");
st.name = Console.ReadLine();
Console.WriteLine("Enter course");
st.course = Console.ReadLine();
al.Add(st);
emp = new Employees();
Console.WriteLine("Enter empID");
emp.empID = int.Parse(Console.ReadLine());
Console.WriteLine("Enter name");
emp.name = Console.ReadLine();
al.Add(emp);
}
Console.WriteLine("/////////////Show Records//////////");
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Roll "+((Student)al[i]).roll.ToString());
Console.WriteLine("Name "+((Student)al[i]).name);
Console.WriteLine("Course "+((Student)al[i]).course);
Console.WriteLine("EmpID "+((Employees)al[i]).empID.ToString());
Console.WriteLine("EmpName "+((Employees)al[i]).name);
}
Console.ReadKey();
}
}
class Student
{
public int roll{ get; set;};
public string name{ get; set;};
public string course{ get; set;};
}
class Employees
{
public int empID{ get; set;};
public string name{ get; set;};
}
}
Your first element is a Student, and you are trying to cast it to Employee on first iteration in the loop.That's why you are getting an InvalidCastException in run-time.Don't use ArrayLists, use strongly-typed generic collections instead.For ex: List<T>.
If you want to display common properties and you want to store Students and Employees into the same list, you can create a common interface for them and implement it.Then you can have a List<CommonInterface> and store your instances.But if you have different properties (it seems you have) you can't access them using common interface or base class,instead you can simply create an extension method and use Reflection to display all property values like this:
public static class Extensions
{
public static string DisplayPerson<T>(this T source)
{
if(source == null) throw new ArgumentNullException("source");
var flags = BindingFlags.Instance | BindingFlags.Public;
var properties = source.GetType().GetProperties(flags);
if (properties.Any())
{
StringBuilder sb = new StringBuilder();
foreach (var prop in properties)
{
sb.AppendFormat("{0} : {1}", prop.Name, prop.GetValue(source));
sb.AppendLine();
}
return sb.ToString();
}
return string.Empty;
}
}
Then just call it from the loop:
for (int i = 0; i < al.Count; i++)
{
Console.WriteLine(al[i].DisplayPerson());
}
Edit: Another way using common interface
public interface IPerson
{
string Name { get; set; }
int Id { get; set; }
}
class Student : IPerson
{
/* implement the properties */
}
class Employees : IPerson
{
/* implement the properties */
}
static void Main(string[] args)
{
List<IPerson> personList = new List<IPerson>();
personList.Add(new Student {/* set properties */});
personList.Add(new Employee {/* set properties */});
// use a loop and display your properties without casting
}
in your array list, your 0th element is a student type and 1st element is an employee type.
in your loop, then you're trying to cast your 0th element to an employee to display empID.
hence you need to be aware of this..
you need to do proper cast check for the loop to work.
check if the element is student or employee and display accordingly.
for (int i = 0; i < al.Count; i++)
{
var student = al[i] as Student;
if (student != null)
{
Console.WriteLine("Roll "+ student.roll.ToString());
Console.WriteLine("Name "+ student.name);
Console.WriteLine("Course "+ student.course);
}
else
{
var employee = al[i] as Employee;
if (employee != null)
{
Console.WriteLine("EmpID "+ employee.empID.ToString());
Console.WriteLine("EmpName "+ employee.name);
}
}
}
though this works for your problem, in general you should be using strongly types collections.
e.g. List<Student> and List<Employee>
You need two lists, because you are trying to store two different types of objects in the array. While it's possible to manage this, you'd be better off keeping it simple: have an array for students and an array for employees.
I'm not sure why you enter the student and employee records at the same time, in pairs. Are the employees connected to the students in some way? Are the students employees? If so, you'd be better off creating a single object that represents student-employee, or whatever the relationship is, and filling a single list with items of that type.
Also, it's 2014 and you shouldn't be using ArrayList. At the very least, use List<>.

Categories

Resources