C# How correctly work get and set? - c#

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.

Related

Messagepack "partial" serialization

I have a class with some private and public fields and properties.
[MessagePackObject(false)]
public class Person
{
[Key(1)]
public string Name { get; set; }
[IgnoreMember]
private int _age;
[Key(2)]
public int Age { get { return _age; } set { _age = value; } }
}
In some cases I don't need to serialize Age, I need to serialize only some fields (for example only Name). So I need 2 methods, to serialize all object and partial serialize. How can I organize it?
Answering to my own question.
The only solution I have found is to move Name to base class BasePerson. I will serialize object as BasePerson and then deserialize bytes to Person
[MessagePackObject(false)]
public class BasePerson
{
[Key(1)]
public string Name { get; set; }
}
[MessagePackObject(false)]
public class Person
{
[IgnoreMember]
private int _age;
[Key(2)]
public int Age { get { return _age; } set { _age = value; } }
}
Usage:
Person person = new Person()
{
Name = "Gor",
Age = 26
};
var serializedBytes = MessagepackSerializer.Serialize<BasePerson>(person);
// will give me person with `Name` "Gor" and `Age` 0 (default value of int)
var personWithoutAge = MessagepackSerializer.Deserialize<Person>(serializedBytes );

instantiating class gives that the name does not exist

I am trying to learn OOP by creating a small program that reads a list of people and outputs only those who are older than 30 using two classes Person and PollParticipant. I am instantiating a new person from my person class and adding name and age:
Person person = new Person(name,age);, which are defined in a constructor, but when I do so it gives me an error that the name 'name' does not exist in the current context. My fields are set to public, so it should be able to access them, what am I doing wrong?
Here is my Person class:
namespace Poll_Opinion
{
public class Person
{
public string name;
public int age;
public Person(string name, int age)
{
this.name = Name;
this.age = Age;
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
}
}
}
}
My poll participants class:
namespace Poll_Opinion
{
class PollParticipant
{
public List<Person> pollParticipant;
public PollParticipant()
{
this.pollParticipant = new List<Person>();
}
public void AddMember(Person participant)
{
this.pollParticipant.Add(participant);
}
public Person ShowOlderMembers()
{
return this.pollParticipant.OrderByDescending(p => p.age).First();
}
}
}
And my Program.cs where I make the instantiation:
namespace Poll_Opinion
{
class Program
{
static void Main(string[] args)
{
PollParticipant pollparticipant = new PollParticipant();
int n = int.Parse(Console.ReadLine());
for (int i = 0; i < n; i++)
{
string[] input = Console.ReadLine().Split();
int age = int.Parse(input[i]);
Person person = new Person(name,age);
pollparticipant.AddMember(person);
}
}
}
}
You have two issues. The first is here:
Person person = new Person(name,age);
You try to pass name and age to the Person constructor but you have not instantiate them.
The second problem is in your constructor:
public Person(string name, int age)
{
// this.name = Name;
this.name = name;
// this.age = Age;
this.age = age;
}
You need to assign name parameter to this.name field, not Name property. In you case you assign this.name to this.name:
this.name = Name; // => where 'Name' get method return this.name
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
By the way, you don't need a public field name (that should be private) in this case. Just do:
public string Name { get; set; }
In C# the properties pratically already have an hidden private field.
name is not defined in your Main() function when you are creating the Person objects.

How to assign a reference type to value type (create copy at value type)

I have a class, below:
public Person(string name, int age)
{
Name = name;
Age = age;
}
After the class is declared, I have the following:
String OtherName;
Int OtherAge;
Person jane = new Person("Jane", 28);
OtherName = Jane.Name;
OtherAge = Jane.Age;
How do I store OtherName and OtherAge in such a way that they do not change when I change the value of jane?
The variables OtherName and OtherAge, as it stands, are going to keep their values, even if the value of jane, or its properties, are updated.
I refactor Person class in the following, If name changes, other name will change. But Other name could change not to effect name prop.
public class Person
{
public Person(string name, int age)
{
Name = name;
Age = age;
}
private string name;
public string Name
{
get { return name; }
set { otherName = name = value; }
}
private int age;
public int Age
{
get { return age; }
set { otherAge = age = value; }
}
private string otherName;
public string OtherName
{
get { return otherName; }
set { otherName = value; }
}
private int otherAge;
public int OtherAge
{
get { return otherAge; }
set { otherAge = value; }
}
}
Example:
static void Main(string[] args)
{
Person jane = new Person("Jane", 28);
jane.OtherName = jane.Name;
jane.OtherAge = jane.Age;
jane.Name = "Dave";
jane.Age = 30;
Console.WriteLine(jane.Name);
Console.WriteLine(jane.Age);
Console.WriteLine(jane.OtherName);
Console.WriteLine(jane.OtherAge);
Console.ReadKey();
}
Output:
Dave
30
Dave
30

C# related on Constructor and Property

I am building some tiny lib, and I have run into a problem.
I want to provide a two-way solution, for example:
How can I accomplish this?
I am getting exception thrown, because it expects something... Any example that will do is welcomed :) Thanks!
EDIT: I am executing something, initially my code is similar to this one:
System.IO.DriveInfo d = new System.IO.DriveInfo("C:");
I want to achieve with my class the following:
Driver d = new Driver();
d.DriverLetter = "C:";
And still get the same results, I use ManagementObjectSearch, ManagementObjectCollection and some other System.Management classes.
You need to provide both constructors:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Country { get; set; }
// Paramterless constructor - for new Person();
// All properties get their default values (string="" and int=0)
public Person () { }
// Parameterized constructor - for new Person("Joe", 16, "USA");
public Person (string name, int age, string country)
{
Name = name;
Age = age;
Country = country;
}
}
If you define a parameterized constructor, the default parameterless constructor is not included for you. Therefore you need to include it yourself.
From MSDN 10.10.4 Default constructors:
If a class contains no instance constructor declarations, a default instance constructor is automatically provided.
You have to define a constructor that takes those three arguments:
public class Person
{
public Person(string name, string age, string country)
{
this.Name = name;
this.Age = age;
this.Country = country;
}
}
This way, you can assign the values to the properties when the class is constructed. You can have more than one constructor for a class taking different parameters and you can have one constructor call another constructor with : this() syntax:
public class Person
{
public Person()
: this(string.Empty, string.Empty, string.Empty)
{
}
public Person(string name, string age, string country)
{
this.Name = name;
this.Age = age;
this.Country = country;
}
}
Here the "empty" constructor will call the other constructor and set all properties to empty strings.
Try this:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Country { get; set; }
public Person()
{
}
public Person(string name, int age, string country)
{
Name = name;
Age = age;
Country = country;
}
}
class Test
{
static void Main(string[] args)
{
var person1 = new Person();
person1.Name = "Joe";
person1.Age = 2;
person1.Country = "USA";
var person2 = new Person("John", 4, "USA");
}
}
The .NET Framework will implicitly provide a default/parameterless constructor if you don't define a constructor. If you define a parameterized constructor, though, you need to explicitly define a default constructor too.
You probably missing your Age property type as int or string.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Country { get; set; }
public Person()
{
}
public Person(string name, int age, string country)
{
this.Name = name;
this.Age = age;
this.Country = country;
}
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person("Erik", 16, "United States");
Person p2 = new Person();
p2.Name = "Erik";
p2.Age = 16;
p2.Country = "United States";
}
}
EDIT: Also you need parameterless constructor for also.

Object initialization in 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.

Categories

Resources