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.
Related
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
In C# properties, where is the 'value' variable defined? I can see it used in the bodies of setters before it is defined anywhere.
namespace TestBindings
{
public class Dog
{
private decimal age;
private string name;
private const int AgeFactor = 7;
public Dog(decimal age, string name)
{
this.age = age;
this.name = name;
}
public decimal AgeDogYears
{
get { return age / AgeFactor; }
set { age = value * AgeFactor; }
}
public decimal AgeHumanYears
{
get { return age; }
set { age = value; } //here
}
public string Name
{
get { return name; }
set { name = value; } // and here
}
}
}
The 'value' variable is automatically passed in from the use-site and is a pre-defined variable name for the value passed in the set expression.
e.g.
var jack = new Dog(13, "jack");
jack.Name = "Jackson";
Here the value after the = sign is being passed into the setter defined in the class as 'value'.
public string Name
{
get { return name; }
set { name = value; } //here
}
It's roughly equivalent to the Java expression it replaces of having an explicit getter and setter method, just using different syntax in order to unify settings fields and properties.
e.g.
public class Dog {
private double age;
private String name;
private final int AgeFactor = 7;
public Dog(double age, String name) {
this.age = age;
this.name = name;
}
public double getAgeHumanYears() {
return age;
}
public void setAgeHumanYears(double value) {
this.age = value;
}
public double getAgeDogYears() {
return age / AgeFactor;
}
public void setAgeDogYears(double value) {
age = value * AgeFactor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
With our test changing to.
private Dog jack = new Dog(13, "jack");
jack.setName("Jackson");
I would like to know if it is possible to know which constructor has been called to create an instance of an object.
For Example:
public class Dog
{
public string Name;
public int Age;
public Dog(){}
public Dog(string n, int age)
{
this.Name = n;
this.Age = age;
}
public Dog(string n)
{
this.Name = n;
}
}
Now I create a class instance:
var dog = new Dog("pippo", 10);
Now (I think with reflection) I want to know from "var dog" which constructor i have used to create a Dog instance if the class has more then one, is it possible?
Thanks.
public enum UsedConstructor { Default, Name, NameAndAge };
public class Dog
{
UsedConstructor UsedConstructor { get; }
public string Name;
public int Age;
public Dog()
{
UsedConstructor = UsedConstructor.Default;
}
public Dog(string n, int age)
{
UsedConstructor = UsedConstructor.NameAndAge;
this.Name = n;
this.Age = age;
}
public Dog(string n)
{
UsedConstructor = UsedConstructor.Name;
this.Name = n;
}
No, it's not possible and also should be unnecessary to know which constructor was called. If you are in that constructor you know already where you are. If you are in the caling code you also know what constructor you have called.
You could store related informations in a variable. For example:
bool dogWithAge = true;
var dog = new Dog("pippo", 10);
// ....
if(dogWithAge)
{...}
else
{...}
If it's so important that you need to know whether the dog was created with an age or not you could also modify the class.
public class Dog{
public string Name { get; set; } // use public properties not fields
public int Age { get; set; } // use public properties not fields
//...
public bool IsAgeKnown { get; set; }
public Dog(string n, int age){
this.IsAgeKnown = true;
this.Name = n;
this.Age = age;
}
}
Now you can always check that property: if(dog.IsAgeKnown) ...
Another approach which works in this case: use a Nullable<int> instead of an int. Then you can use if(dog.Age.HasValue).
If you want to know that in runtime, you can set a flag in this object. If in debug - set a breakpoint in both constructors.
public class Dog{
public string Name;
public int Age;
public string CreatedBy;
public Dog(){
this.CreatedBy = "parameterless constructor";
}
public Dog(string n, int age){
this.Name = n;
this.Age = age;
this.CreatedBy = "two parameters constructor";
}
public Dog(string n){
this.Name = n;
this.CreatedBy = "one parameter constructor";
}
}
You can use enum as well.
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.
Can I create an object from class person inside a class employee and access to the methods and members of class person through employee class using the person’s object that I created in class employee
public class Person
{
protected string _name;
public int _age;
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
}
class Employee
{
Person person = new Person();
}
Do you mean this?
public class Employee
{
private Person person = new Person();
public string Name
{
get { return person.Name; }
set { person.Name = value; }
}
public int Age
{
get { return person.Age; }
set { person.Age = value; }
}
}
You could do:
class Employee
{
Person person = new Person();
public string Name
{
get { return person.Name; }
set { person.Name = value }
}
public int Age
{
get { return person.Age; }
set { person.Age = value; }
}
}
You could look at providing a 'person' interface and letting the employee class implement it.
Yes, because class Person is public.