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");
Related
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.
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
I have a class and I am using it inside a LIST
List<user> listWithCustomClass = List<user>();
myClass.cs
public class user
{
public user(string fullname, string city, string state, int age, int type)
{
name = fullname;
citi = city;
estate = state;
tipe = type;
}
private string name = string.Empty;
private string citi = string.Empty;
private string estate = string.Empty;
private int tipe = 0;
public string getFullname
{
get { return name; }
set { name = value;}
}
public string getCity
{
get { return citi; }
set { citi = value;}
}
public string getState
{
get { return state; }
set { state = value;}
}
public int getType
{
get { return type; }
set { type = value;}
}
}
How can I add a custom toString() without having to override generic toString(). I would like to add something like showDate().
For example, in a combobox I would like the output of the inserted information to be:
--> Hello, your name is {name} and your age is {age}
Like this:
foreach(var item in user)
{
user.ShowData();
}
Add this in your class:
public string ShowData()
{
return "Hello, your name is " + name + " and your age is " + age.ToString();
}
but you must also define age first. Which, following your style, would be:
private int age = 0;
and then in the constructor add:
this.age = age;
EDIT
foreach(var item in listWithCustomClass)
{
item.ShowData();
}
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 getting an error as followed:
Inconsistent accessibility: property type 'AudioDevices.Tracks.track.Time' is less accessible than property 'AudioDevices.Tracks.track.length'
I have no clue what it is, or how i can fix it. Anybody that can help me?
This is all the code i have, [template = class library]:
namespace AudioDevices.Tracks
{
public class Track
{
#region STRUCT
private int id;
private string name;
private string artist;
private string albumSource;
private Time length;
private category style;
public enum category{
Ambient, Blues, Country, Disco, Electro, Hardcore, HardRock, HeavyMetal, Hiphop, Jazz, Jumpstyle,
Klassiek, Latin, Other, Pop, Punk, Reggae, Rock, Soul, Trance, Techno
};
#endregion
#region GET/SET
public int Id{
get { return id; }
set { id = value; }
}
public string Name{
get { return name; }
set { name = value; }
}
public string Artist{
get { return artist; }
set { artist = value; }
}
public string AlbumSource{
get { return albumSource; }
set { albumSource = value; }
}
public Time Length{
set { length = value; }
}
public string DisplayTime
{
get { return length.ToString(); }
}
public category Style
{
get { return style; }
set { style = value; }
}
#endregion
#region TIME CONSTRUCTOR
struct Time
{
int seconds;
int minutes;
int hours;
public Time(int seconds)
{
this.seconds = seconds;
this.minutes = 0;
this.hours = 0;
}
public Time(int seconds, int minutes)
{
this.seconds = seconds;
this.minutes = minutes;
this.hours = 0;
}
public Time(int seconds, int minutes, int hours)
{
this.seconds = seconds;
this.minutes = minutes;
this.hours = hours;
}
public override string ToString()
{
return hours + ":" + minutes + ":" + seconds;
}
}
#endregion
#region TRACK CONSTRUCTOR
public Track(){ }
public Track(int id)
{
this.id = id;
}
public Track(int id, string name)
{
this.id = id;
this.name = name;
}
public Track(int id, string name, string artist)
{
this.id = id;
this.name = name;
this.artist = artist;
}
#endregion
#region GetLength
public string GetLength()
{
return length.ToString();
}
public int GetLengthInSeconds(int seconds, int minutes, int hours){
int SecondsToSeconds = seconds;
int MinutesToSeconds = minutes * 60;
int HoursToSeconds = hours * 3600;
int TotalSeconds = HoursToSeconds + MinutesToSeconds + SecondsToSeconds;
return TotalSeconds;
}
#endregion
}
}
You've got a public property here:
public Time Length{
set { length = value; }
}
... but the type of that property is Time, which is a private type:
struct Time {
...
}
(It's private because it's a nested type; if it were declared as a top-level type it would be internal by default, which would still have the same problem.)
Public member signatures can't refer to private or internal types anywhere in the parameter types or return type. The member simply wouldn't be meaningful to the caller if they were in a different assembly.
So, the fix is to either make Time a public type (and I'd recommend extracting it as a top-level type at the same time) or to make Time a private property.
From MSDN;
The access level for class members and struct members, including
nested classes and structs, is private by default.
So, your Time struct is private by default.
On this part;
public Time Length
{
set { length = value; }
}
You are trying to create public property the type of private struct. You can't do that. For fixing it,
Change your Length property access modifier public to private.
or
Set your Time struct access modifier to public.
This might be because you are using a construct Time.
Try to alter your code like:
public Time Length{
set { length = new Time(value); }
}