Object initialization in C# - c#

When i have declaration like:
class Professor
{
string profid;
public string ProfessorID
{
get { return profid;}
set { profid=value;}
}
student st;
}
class student
{
string name;
string id;
public string Name
{
get { return name;}
set { name=value; }
}
public string StudentID
{
get { return id;}
set { id=value; }
}
}
public void GetDetails()
{
Professor prf=new Professor(){ ProfessorID=1, how to initialize student here?};
}
Inside GetDetails() how can i initialize student ?

First make it accessible:
public student Student { get; set; }
then something like:
Professor prf = new Professor()
{
ProfessorID = "abc",
Student = new student { Name = "Marc", StudentID = "def" }
};
Note that if the property is get-only:
private readonly student _student = new student();
public student Student { get { return _student; }}
Then you can use the alternative syntax (which sets properties without attempting to change the student reference):
Professor prf = new Professor()
{
ProfessorID = "abc",
Student = { Name = "Marc", StudentID = "def" }
};

Your Professor class will need a property setter for the student, at which point you can write:
public void GetDetails()
{
Professor prf = new Professor {
ProfessorID = "1",
Student = new Student { Name = "Jon", StudentID = "1" }
};
}
Without that property, nothing in the Professor class will set the st variable at all.
Note that because in both cases we're only using the parameterless constructor, I've removed the explicit () from the object initializer.
Further note: automatically implemented properties can make your code a lot shorter:
class Professor
{
public string ProfessorID { get; set; }
public Student Student { get; set; }
}
class Student
{
public string Name { get; set; }
public string StudentID { get; set; }
}

You should make property Student in Professor:
class Professor
{
string profid;
public string ProfessorID
{
get { return profid; }
set { profid = value; }
}
student st;
public student Student { // New property
get { return st; }
set { st = value; }
}
}
class student
{
string name;
string id;
public string Name
{
get { return name; }
set { name = value; }
}
public string StudentID
{
get { return id; }
set { id = value; }
}
}
public void GetDetails(){
Professor prf=new Professor(){ ProfessorID="1", Student = new student()};
}

You need an accessor for your student within Professor
class Professor
{
string profid;
public string ProfessorID
{
get { return profid;}
set { profid=value;}
}
public Student {
get { return st;}
set { st=value;}
}
student st;
}
public void GetDetails()
{
Student s = new Student();
s.StudentId = someId;
s.name = someName;
Professor prf = new Professor { ProfessorID=1, Student = s;};
}
However, your current model is 1 Prof : 1 Student, are you sure this is what you want?

Following up on John's answer:
You want parentheses, not brackets, but a public constructor is typically the right approach. The other way to do it is a no-argument constructor with public properties.

Related

Set property not called for List object

Could someone help me below?
It seems Set is not called. How can I get around this?
Note that _students is set as the selectedObject of a property grid. So adding is done in the UI.
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Record
{
List<Student> _students = new List<Students>();
public List<Student> Students
{
get
{
return _students;
}
set
{
// track changes here...
MessageBox.Show("value set!"); // this doesn't get called
_students = value;
}
}
}
I think you're having an issue with what set does with a list. You'll never see the message on adding a student to Record.Students, only when you set the list.
void Main()
{
Student s = new Student() {
Name = "fred",
Age = 10
};
List<Student> _s = new List<Student>();
_s.Add(s);
Record r = new Record();
r.Students = _s; //You'll get a message here
r.Students.Add(s); //No message here
}
// Define other methods and classes here
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Record
{
List<Student> _students = new List<Student>();
public List<Student> Students
{
get
{
return _students;
}
set
{
// track changes here...
MessageBox.Show("value set!");
_students = value;
}
}
}
Right now, you just set _students.
If you want that setter to execute, you're gonna have to go Students = new List<Student<(); instead of _students = new List<Student>();.

Get Property Value of Nested Classes is always null

I have following two classes
public class Family
{
public string ChildName { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public Family Child { get; set; }
}
I have an instance of Employee class as follows.
Employee employee = new Employee();
employee.Name = "Ram";
employee.Id = 77;
employee.Child = new Family() { ChildName = "Lava" };
I have a method which gets the property value based on the property name as follows:
public static object GetPropertyValue(object src, string propName)
{
string[] nameParts = propName.Split('.');
if (nameParts.Length == 1)
{
return src.GetType().GetRuntimeProperty(propName).GetValue(src, null);
}
foreach (String part in nameParts)
{
if (src == null) { return null; }
Type type = src.GetType();
PropertyInfo info = type.GetRuntimeProperty(part);
if (info == null)
{ return null; }
src = info.GetValue(src, null);
}
return src;
}
In the above method,when I try to get property value of nested class like
GetPropertyValue(employee, "employee.Child.ChildName")
or
GetPropertyValue(GetPropertyValue(employee, "Family"), "ChildName"
doesn't return any value because type.GetRuntimeProperty(part) is always null.
Is there any way to fix this problem?
You problem lies in this line:
foreach (String part in nameParts)
Because you are iterating over each part of nameParts, you are also iterating over "employee", which of course is not a valid property.
Try either this:
foreach (String part in nameParts.Skip(1))
Or calling the method like this:
GetPropertyValue(employee, "Child.ChildName")
(Notice no "employee.", because you already pass in an employee)
The problem in this case is that when you split the string employee.Child.ChildName, the "employee" is the first part. However, employee is not a property of the source i.e. Employee Class.
Try this:
public class Program
{
public static void Main()
{
Employee employee = new Employee();
employee.Name = "Ram";
employee.Id = 77;
employee.Child = new Family() { ChildName = "Lava" };
GetPropertyValue(employee, "employee.Child.ChildName");
}
public class Family
{
public string ChildName { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public Family Child { get; set; }
}
public static object GetPropertyValue(object src, string propName)
{
string[] nameParts = propName.Split('.');
if (nameParts.Length == 1)
{
return src.GetType().GetRuntimeProperty(propName).GetValue(src, null);
}
nameParts = nameParts.Skip(1).ToArray();
foreach (String part in nameParts)
{
if (src == null) { return null; }
Type type = src.GetType();
PropertyInfo info = type.GetRuntimeProperty(part);
if (info == null)
{ return null; }
src = info.GetValue(src, null);
}
return src;
}
Here, i have skipped the first part of the string i.e. "employee". However, you can solve the problem by passing Child.ChildName
This question is around 2 years old, but I found a another working solution for you question, which is easy to understand. If you initialize the object in calling calss constructor you can use dot(.) notation to assign or read property. Example -
public class Family{
public string ChildName { get; set; }
}
public class Employee{
public int Id { get; set; }
public string Name { get; set; }
public Family Child { get; set; }
public Employee(){
Child = new Family();
}
}
Employee emp = new Employee();
emp.Family.ChildName = "Nested calss attribute value";

Adding a string variable in a list everytime the class is provided by information

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment5
{
public class Person
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
}
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public static int countS = 0;
public static List<string> studentlist = new List<string>();
public Student()
{
studentlist.Add(Name);
countS++;
}
public static int GetActiveInstances()
{
return countS;
}
}
class MainProgram
{
static void Main(string[] args)
{
// Instantiate three Student objects.
Student Student1 = new Student();
Student Student2 = new Student();
Student Student3 = new Student();
Student1.Name = "John";
Student2.Name = "Joe";
Student3.Name = "Jacob";
for (int i = 0; i < Student.studentlist.Count; i++) // Loop with for.
{
Console.WriteLine(Student.studentlist[i]);
}
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
}
}
Hi guys. What I have in mind is that I want to automatically store every student being initiated in an array/list that I created and eventually, I want to output these students in the console.
Can anyone enlighten me what I did wrong on my program?
Supposedly it will output the 3 names I declare. What I have on the output for the posted program are all blank.
**Next Related Question **
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment6
{
public class Person
{
public string Name { get; set; }
public string Address { get; set; }
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", Name);
Console.WriteLine("Address: {0}", Address);
}
}
public class Student : Person
{
public void SetStudentInfo(string name, string address)
{
Name = name;
Address = address;
}
}
public class Course //class represents university course
{
private ArrayList studentList = new ArrayList();
public ArrayList StudentList
{
get { return studentList; }
set { studentList = value; }
}
//how can I implement this such that I can have the StudentList be updated and printed
// out to the console from the main
public void ListStudents()
{
foreach (Student i in StudentList)
{
Console.WriteLine(i.ToString());
}
}
}
class MainProgram
{
static void Main(string[] args)
{
var Student1 = new Student { Name = "John" };
var Student2 = new Student { Name = "Joe" };
var Student3 = new Student { Name = "Jacob" };
Course course1 = new Course();
course1.StudentList.Add(Student1);
course1.StudentList.Add(Student2);
course1.StudentList.Add(Student3);
course1.ListStudents();
Console.WriteLine();
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
}
}
I have this code and I want to output every student in my arraylist, the foreach loop should be on the course class. Still, the code is connected on my question so I just ask it here. Can anyone help me revise it? thanks
What I do not get is these line:
public static int countS = 0;
public static List<string> studentlist = new List<string>();
public Student()
{
studentlist.Add(Address);
countS++;
}
What I would suggest is to move these out so that the class is something like this:
public class Person
{
public string Name { get; set; }
public DateTime BirthDate { get; set; }
}
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
And that main is something like this:
static void Main(string[] args)
{
// Instantiate three Student objects.
Student Student1 = new Student();
Student Student2 = new Student();
Student Student3 = new Student();
Student1.Name = "John";
Student2.Name = "Joe";
Student3.Name = "Jacob";
var studentlist = new List<Student>{Student1,Student2,Student3};
foreach (var student in studentlist)
{
Console.WriteLine(student.Name);
}
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey();
}
Instead of adding a property that hasn't been set yet (which is what you're currently doing in the default constructor - you're adding the Name property before it's been set), you can add a reference to the class instance using the this keyword, so the properties of the items in your list (like Name or Address) get updated when they are set on the class instance.
Also, you don't need a separate variable to keep track of the number of students, since you can just use the Count property of the list.
Here's a way you can do this:
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public static List<Student> AllStudents = new List<Student>();
public Student()
{
AllStudents.Add(this);
}
public static int GetActiveInstances()
{
return AllStudents.Count;
}
}
Usage:
public static void Main()
{
var student1 = new Student {Name = "John"};
var student2 = new Student {Name = "Joe"};
var student3 = new Student {Name = "Jacob"};
foreach (var student in Student.AllStudents)
{
Console.WriteLine(student.Name);
}
}
Output:
JohnJoeJacob
UPDATE
One way you can protect your internal list, yet still let others query it, would be to make the list private, and then expose a public property that returns a copy of the list, which prevents people from affecting your private instance if they call .Add() or .Remove() on it, or try to set it to a new List<Student>.
Here's an example:
public class Student : Person
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
// This is the "official" list. It's private so cannot be changed externally
private static readonly List<Student> StudentList = new List<Student>();
// This property returns a COPY of our private list
public static List<Student> AllStudents
{
get
{
var copyOfList = new List<Student>();
copyOfList.AddRange(StudentList);
return copyOfList;
}
}
public Student()
{
// Add the student to our private list
StudentList.Add(this);
}
public static int StudentCount()
{
// Return the count from our private list
return StudentList.Count;
}
}

C# How correctly work get and set?

I am beginner in programming and I want to ask you probably the easiest question.
I did something like this:
class person
{
private string name;
public string surname;
private int year;
}
class student : person
{
}
class Program
{
static void Main(string[] args)
{
List<student> list = new List<student>();
list.Add(new student()
{
surname = "jordan"
// name ... ???
// year .. ?
});
}
}
How can I correctly use get and set if I have private field or how can I assign a value to name or year?
You can set private property in constructor like this:
public class person
{
private string name { get; set; };
public string surname { get; set; };
private int year { get; set; };
public person(string name, int year)
{
this.name = name;
this.year = year;
}
}
public class student : person
{
public student(string name, int year) : base (name, year) { };
}
and use can be:
list.Add(new student("name", 45)
{
surname = "jordan"
});
(Note the use of Upper case for classes and properties, lower case reserved for fields and local variables).
Declare as public properties like so:
class Person
{
public string Surname {get; set;}
}
Usage:
new Person{
Surname = "jordan"
};
Or with private setters, and set in constructor.
class Person
{
public Person(string surname)
{
Surname = surname;
}
public string Surname {get; private set;}
}
Usage:
new Person("jordan");
Or private fields, also set in constructor (same usage).
class Person
{
private string surname;
public Person(string surname)
{
this.surname = surname;
}
public string Surname {get{return surname;}}
}
Even if the fields are private you can provide public properties. You should do that anyway since the fields should not be accessible from outside, all the more if they are just backing fields for properties.
class person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string surname;
public string Surname
{
get { return surname; }
set { surname = value; }
}
private int year;
public int Year
{
get { return year; }
private set { year = value; }
}
}
Now the fields are private and you can change the access modifiers of the properties according to your needs. You can even make the setter private as shown in the Year property.
List<Person> list = new List<Person>();
list.Add(new Person()
{
Name = "Michael",
Surname = "jordan",
});
Now you cannot modify the Year from outside since it's private. You could provide an appropriate constructor to initialize it.

c# merge objects

Class Person
{
string Name
int yesno
int Change
List<Cars> Personcars;
houses Personhouses
}
Person user1 = new Person()
Person user2 = new Person()
user1.Name = "userName"
user2.Name ="";
user2.cars[0] = new car("Mazda");
user1.cars[0] = new car("BMW");
i want to merge the objects so that user2 will take the name and the car from user1
user2 will have this values
user2.Name will be userName
user2.cars will hold the Mazda and the Bmw
thanks !
user2.Name = user1.Name;
user2.Personcars.AddRange(user1.Personcars);
You could add this as a method on the class itself:
public class Person
{
List<Cars> _personcars;
public string Name { get; set; }
// what the hell is a yesno int? If it's 1 or 0 then just use a bool
public int yesno { get; set; }
public int Change { get; set; }
public List<Cars> Personcars
{
get
{
return _personcars ?? (_personCars = new List<Cars>());
}
set { _personcars = value; }
}
public Houses Personhouses { get; set; }
public void Merge(Person person)
{
Name = person.Name;
Personcars.AddRange(person.Personcars);
}
}
Which will allow you to write something like this:
user2.Merge(user1);
Try this extension methods
public void Merge(this Person _person, Person source)
{
_person.Name = source.Name;
if(_person.Cars !=null)
{
_person.Cars.AddRang(source.Cars);
}
else
{
_person.Cars = source.Cars;
}
}

Categories

Resources