Constructor prints text when object is created - c#

I am working in a C# console application and I am learning OOP.
First, I have a Person Class,
class Person
{
public string Name;
public string LastName;
public void Comment()
{
Console.WriteLine("Comment from Person Class");
}
and Student class
class Student : Person
{
public int IndexNr = 171124;
public int totalSubjects;
public Student()
{
Console.WriteLine("Index number=" + IndexNr);
}
public Student(int subjectsTotal,int nr)
{
totalSubjects= nr;
Console.WriteLine("Average grade= " + subjectsTotal/ totalSubjects);
}
public void Comment()
{
Console.WriteLine("Comment from Student class");
}
}
And in the Program.cs in the Main function the code goes like this:
static void Main(string[] args)
{
Console.WriteLine("Student Info");
Student st2= new Student();
st2.Name= "name1";
st2.LastName = "lastname1";
Console.WriteLine("Name=" + st2.Name+ " LastName=" + st2.LastName);
Student st1 = new Student(90,10);
//Polymorphism example -> here is where I need help
Person p1 = new Person();
Person s1 = new Student();
p1.Komenti();
s1.Komenti();
}
So, when I create Person s1 = new Student() object it prints out the the Comment function from only Person class, and not 1 from Person and 1 from Student class.
I have tried the same in Java as well and there it works very well.
Can you please tell me and enlighten me where am I making mistakes or what am I missing?
Thank you.

Try using the override modifier on the Comment method in the Student class https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/override This should then override the person implementation
public class Student : Person
{
public int IndexNr = 171124;
public int totalSubjects;
public Student()
{
Console.WriteLine("Index number=" + IndexNr);
}
public Student(int subjectsTotal,int nr)
{
totalSubjects= nr;
Console.WriteLine("Average grade= " + subjectsTotal/ totalSubjects);
}
public override void Comment()
{
Console.WriteLine("Comment from Student class");
}
}

Related

Type casting in C# .net

I am learning a MOOC course on c#. we had to create an Arraylist of type students and then using the foreach loop had to iterate over it and print the names. i have tried all casting methods but could not get through it. please help
c.students.Add(student1);
c.students.Add(student2);
c.students.Add(student3);
foreach(object o in students)
{
Student s = (Student)o;
Console.WriteLine(s.FirstName);
}
c is the course object. course is a class. students is the arraylist. Student is a class.
Not sure where you face the error. Check out my .NET Fiddle here. Code shown below as well. Hope it helps.
using System;
using System.Collections;
public class Program
{
public static void Main()
{
var students = new ArrayList();
students.Add(new Student() { FirstName = "John", LastName = "Doe" });
students.Add(new Student() { FirstName = "Richard", LastName = "Roe" });
foreach(Student s in students)
{
Console.WriteLine(s.FirstName);
}
}
}
public class Student
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
foreach(object o in c.students)
this should do it, its probably a silly mistake
namespace stackOverflow
{
class Program
{
static void Main(string[] args)
{
course c = new course();
student student1 = new student("a");
student student2 = new student("b");
student student3 = new student("c");
c.students.Add(student1);
c.students.Add(student2);
c.students.Add(student3);
foreach (object o in c.students)
{
student s = (student)o;
Console.WriteLine(s.name);
}
}
}
class course
{
public List<student> students = new List<student>();
}
class student
{
public string name { get; set; }
public student(string s)
{
name = s;
}
}
}
ArrayList students = new ArrayList();
This line should be: c.students = new ArrayList(); as mentioned by Channs previously.
As you have written it, it is trying to create a new variable in your main function called students, it never accesses the students array inside your course object.
Although your initialisation of internal object variables should be done within the object itself.
So inside your course object do something more like this:
class Course
{
public ArrayList students;
public Course()
{
students = new ArrayList();
}
}
This way, whenever you declare a new object of type Course ( ie: Course c = new Course() ) it will initialise the array automatically.
Another issue I noticed was in your Student constructor declaration, you are always trying to take a parameter of string fname.
public Student(string fname)
Then in your code you never pass that data ie:
Student student1 = new Student();
So either pass the firstname variable in when you are initialising or change your constructor in Student to allow it to accept nothing as well as a firstname as shown below:
class Student
{
private string firstName;
private string lastName;
public Student(string fname = null)
{
this.FirstName = fname;
}
this way you don't have to pass the data, but if you do it will be copied over to the firstname of the student object.
You could always change the null to something like "John" or "No Name" so that you have printable data in the object. just a suggestion though.
Regards,
Slipoch
Here is your code fixed up. There were 2 things:
Your student class did not have a default constructor.
Your student array list was not initialized in the course class.
Hope this helps.
using System;
using System.Collections;
class Program
{
public static void Main(string[] args)
{
Student student1 = new Student();
student1.FirstName = "a";
student1.LastName = "w";
Student student2 = new Student();
student2.FirstName = "e";
student2.LastName = "s";
Student student3 = new Student();
student3.FirstName = "i";
student3.LastName = "o";
Course c = new Course();
ArrayList students = new ArrayList();
c.students.Add(student1);
c.students.Add(student2);
c.students.Add(student3);
foreach (Student o in c.students)
{
Student s = (Student)o;
Console.WriteLine(s.FirstName);
}
Console.ReadLine();
}
}
internal class Course
{
public ArrayList students = new ArrayList();
}
internal class Student
{
private string firstName;
private string lastName;
public Student()
{
}
public Student(string fname)
{
this.FirstName = fname;
}
public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}
public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
}
}
}

Detail of class in output using list in c#

Here is my person class:
public class Person
{
public string Name;
public string LastName;
public int Age;
public Person()
{
}
public Person(string name, string lastName, int age)
{
Name = name;
LastName = lastName;
Age = age;
}
}
Here is my main program. The current output is ListDemo.Person. ListDemo is my solution name and Person is my class name. How can I get the all details of a person in an output?
class Program
{
static void Main(string[] args)
{
List<Person> personList = new List<Person>();
personList.Add(new Person { Name = "Ahmad", LastName = "Ashfaq", Age = 20 });
personList.Add(new Person { Name = "Ali", LastName = "Murtza", Age = 23 });
foreach (Person item in personList)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
This is pretty simple.
public class Person
{
public string Name;
public string LastName;
public int Age;
public Person()
{
}
public Person(string name, string lastName, int age)
{
Name = name;
LastName = lastName;
Age = age;
}
public override string ToString()
{
return string.Format("{0} {1} - {2} Years Old", Name, LastName, Age);
}
}
Which you can use exactly how you were in the original place:
foreach (Person item in personList)
{
Console.WriteLine(item);
}
Which will print out like:
Jane Doe - 23 Years Old
John Doe - 14 Years Old
Jim Doe - 120 Years Old
The .ToString() is inherited from Object and is available to override on every class you create. You can use it to return string data that represents the object. By default this just returns the type name ListDemo.Person as you found out, but if you override it, you can return whatever you want.
Edite your code to be like this
class Program
{
static void Main(string[] args)
{
List<Person> personList = new List<Person>();
personList.Add(new Person { Name = "Ahmad", LastName = "Ashfaq", Age = 20 });
personList.Add(new Person { Name = "Ali", LastName = "Murtza", Age = 23 });
foreach (Person item in personList)
{
Console.WriteLine(item.Name);
Console.WriteLine(item.LastName);
Console.WriteLine(item.Age);
}
Console.ReadKey();
}
}
Console.WriteLine("Name = {0}, Last Name = {1}, Age = {2}", item.Name, item.LastName, item.Age);
That will output the data you are looking for by going through the properties in the items and giving you the output you desire.
Likewise, if you are looking for default behavior of generating a string from your class, you can override the ToString() method for your class to give the output you desire.
public override string ToString()
{
return string.Format("Name = {0}, Last Name = {1}, Age = {2}", Name, LastName, Age);
}
You have to override te ToString method in your Person class. The result of that function is what's printed. Insert the following code into your Person class:
public override string ToString() {
return string.Format("Name: {0}, LastName: {1}, Age: {2}", Name, LastName, Age);
}
Alternatively, if you do not want the string representation of your class to change. You could print the string generated with the above code instead of printing the object itself.
Beside of using ToString() method that is useful to output single value i am surprised that no one mentioned that you can create custom extension method for IEnumerable<T> (interface that is implemented by List<T>) to print all your values :
public static class Helper
{
public static void Print(this IEnumerable<Person> people)
{
foreach(Person p in people)
Console.WriteLine(string.Format("Name : {0}, Last Name : {1}, Age : {2}", p.Name, p.LastName, p.Age));
}
}
And use it in a way like if it was defined in List<T> :
class Program
{
static void Main(string[] args)
{
List<Person> personList = new List<Person>();
personList.Add(new Person { Name = "Ahmad", LastName = "Ashfaq", Age = 20 });
personList.Add(new Person { Name = "Ali", LastName = "Murtza", Age = 23 });
personList.Print();
}
}

How count number of objects created with a static class variable?

I created 3 objects of a class and I want to display on the console how many objects I have created (using a static class variable) - How do I do this ?
I put public static int count = 0; in the class I created but I couldn't get it to increment (count++;) based on how many objects I created of the class. I created the 3 objects in the main method and gave them values for variables.
here is the class I created in my program :
public class Student
{
public static int count = 0;
// count++;
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
private string birthDate;
public string BirthDate
{
get { return birthDate; }
set { birthDate = value; }
}
}
In the main method I created 3 objects of class Student:
static void Main(string[] args)
{
// Create 3 students
Student student1 = new Student
{
FirstName = "John",
LastName = "Wayne",
BirthDate = "26/05/1907"
};
Student student2 = new Student
{
FirstName = "Craig",
LastName = "Playstead",
BirthDate ="01/01/1967"
};
Student student3 = new Student
{
FirstName = "Paula",
LastName = "Smith",
BirthDate = "01/12/1977"
};
// Console.WriteLine("The course contains {1} students(s) " studentCounter );
I can't get the counter to ++ based on the way I created the objects.
Increment the count in the constructor:
public class Student
{
public static int count = 0;
public Student()
{
// Thread safe since this is a static property
Interlocked.Increment(ref count);
}
// use properties!
public string FirstName { get; set; }
public string LastName { get; set; }
public string BirthDate { get; set; }
}
You just need a constructor, there you can increment the count.
public Student()
{
count++;
}
You can increment the counter in the constructor
public Student()
{
count++;
}
To print the count variable
we should write some code like below
public static int GetCount()
{
return count;
}
and main class look like :
static void Main(string[] args)
{
// Create 3 students
Student student1 = new Student
{
FirstName = "John",
LastName = "Wayne",
BirthDate = "26/05/1907"
};
Student student2 = new Student
{
FirstName = "Craig",
LastName = "Playstead",
BirthDate ="01/01/1967"
};
Student student3 = new Student
{
FirstName = "Paula",
LastName = "Smith",
BirthDate = "01/12/1977"
};
//To print the count
Console.WriteLine(" Number of Objects is : "+Student.GetCount());
}
and if we have parameterized constructor then we also have to write count++ in that constructor.

Interface Property Usage

I get an error when run the console app since obviously instance of P doesnt exist. What I cant understand is where should be "newing" it? Should it be in the constructor of Employee (that didnt work when I tried) ??
public class Person
{
private string name;
public string Name // read-write instance property
{
get
{
return name;
}
set
{
name = value;
}
}
}
interface IEmployee
{
Person P
{
get;
set;
}
int Counter
{
get;
}
}
public class Employee : IEmployee
{
private Person p;
public static int numberOfEmployees;
public Person P // read-write instance property
{
get
{
return p;
}
set
{
p = value;
}
}
private int counter;
public int Counter // read-only instance property
{
get
{
return counter;
}
}
public Employee() // constructor
{
counter = ++counter + numberOfEmployees;
}
}
class Program
{
static void Main(string[] args)
{
System.Console.Write("Enter number of employees: ");
Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());
Employee e1 = new Employee();
System.Console.Write("Enter the name of the new employee: ");
e1.P.Name = System.Console.ReadLine();
System.Console.WriteLine("The employee information:");
System.Console.WriteLine("Employee number: {0}", e1.Counter);
System.Console.WriteLine("Employee name: {0}", e1.P.Name);
Console.ReadLine();
}
}
Yes, somewhere in your program you are missing the line
e1.P = new Person();
Either right in front of reading the name, or maybe in the constructor of Employee.
If you modify your code like this, it will work
class Program
{
static void Main(string[] args)
{
System.Console.Write("Enter number of employees: ");
Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());
Employee e1 = new Employee();
e.P = new Person(); //add this line
System.Console.Write("Enter the name of the new employee: ");
e1.P.Name = System.Console.ReadLine();
System.Console.WriteLine("The employee information:");
System.Console.WriteLine("Employee number: {0}", e1.Counter);
System.Console.WriteLine("Employee name: {0}", e1.P.Name);
Console.ReadLine();
}
}

How to add the data from different class in one XML file?

I have a three classes i want to add the all classes data in one XML file?
fist class is:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public override string ToString()
{
return FirstName + " " +LastName + " " +Email;
}
}
second class is :
public class Student:Person
{
public Student()
{
}
public double AssessmentGrade { get; set; }
public double AssignmentGrade { get; set; }
public override string ToString()
{
return base.ToString() + "," +AssessmentGrade + "," + AssignmentGrade;
}
}
Third Class is:
public class Teacher:Person
{
public string RoomNumber
{
get;
set;
}
public override string ToString()
{
return base.ToString() + "," + RoomNumber;
}
}
I made a DB Class too where i store all the data in XML file.
private const string path = #"Persons.xml";
Public static void SavePersons(List<Person> Persons)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
XmlWriter xmlOut = XmlWriter.Create(path, settings);
xmlOut.WriteStartDocument();
xmlOut.WriteStartElement("Persons");
foreach (Person person in Persons)
{
Student student = new Student();
Teacher teacher = new Teacher();
xmlOut.WriteStartElement("Person");
xmlOut.WriteAttributeString("Email", person.Email);
xmlOut.WriteElementString("Firstname", person.FirstName);
xmlOut.WriteElementString("Lastname", person.LastName);
xmlOut.WriteElementString("AssessmentGrade",
student.AssessmentGrade.ToString());
xmlOut.WriteElementString("AssignmentGrade",
student.AssignmentGrade.ToString());
xmlOut.WriteElementString("Room", teacher.RoomNumber.ToString());
xmlOut.WriteEndElement();
}
xmlOut.WriteEndElement();
xmlOut.Close();
}
Now problem is this how to add Student Class and Teacher class in the Same XML.I tried to add but it doesn't work.Can you please help me.
I think what you want to do is store Person, Student and Teacher separately, but in the same file, and using the same logic? Maybe something like this:
foreach (Person person in Persons)
{
// Edit: After reading the comment below, I
// updated the methods to return an XmlWriter. This
// way, you should be able to contiune working with the
// same instance:
if(typeOf(Student).IsInstanceOfType(person)){
xmlOut = AppendStudentInfo(person, xmlOut);
}else if(typeOf(Teacher).IsInstanceOfType(person){
xmlOut = AppendTeacherInfo(person, xmlOut);
}else{
xmlOut = AppendPersonInfo(person, xmlOut);
}
}
xmlOut.WriteEndElement();
xmlOut.Close();
(...)
Then create three helper-methods to write the data. This is an example for Students:
// (Edit: Updated to return an XmlWriter)
private XmlWriter AppendStudentInfo(Person person, XmlWriter xmlOut){
Student student = (Student) person;
// For teacher, use this instead:
// Teacher teacher = (Teacher) person;
xmlOut.WriteStartElement("Student");
xmlOut.WriteAttributeString("Email", student.Email);
xmlOut.WriteElementString("Firstname", student.FirstName);
xmlOut.WriteElementString("Lastname", student.LastName);
xmlOut.WriteElementString("AssessmentGrade",
student.AssessmentGrade.ToString());
xmlOut.WriteElementString("AssignmentGrade",
student.AssignmentGrade.ToString());
xmlOut.WriteEndElement();
// (Edit: Updated to return an XmlWriter)
return xmlOut;
}
Now for Teacher, you would do the same, but using that type instead of Student, and including fields relevant to the teacher-type (ie Room instead of AssignmentGrade and AssessmentGrade).
For Person, you would do the same, but only include the fields that exist in the class Person.
I haven't tested this code, but believe it should be more or less correct. Hope this was something like the answer you were looking for.
From what I can see in your code it should be erroring out on these three lines. :
xmlOut.WriteElementString("AssessmentGrade", student.AssessmentGrade.ToString());
xmlOut.WriteElementString("AssignmentGrade", student.AssignmentGrade.ToString());
xmlOut.WriteElementString("Room", teacher.RoomNumber.ToString());
This is because you declare your new student and teacher objects above but you do not provide a value for AssessmentGrade/AssignmentGrade/RoomNumber.
Am I understanding what your issue is?
student.AssessmentGrade = 90;
Use DataContractSerializer to serialize data in xml format:
Public static void SavePersons(Persons persons)
{
var serializer = new DataContractSerializer(typeof(Persons));
// Create a FileStream to write with.
FileStream fs = new FileStream("file.xml", FileMode.Create);
using (fs)
{
ser.WriteObject(fs, p);
}
}
Class Persons:
[KnownType(typeof(Student))]
[KnownType(typeof(Teacher))]
[DataContract]
public class Persons
{
[DataMember]
public IEnumerable<Person>{get;set;}
}
Another example on it:MSDN article

Categories