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.
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 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.
Hey guys I want to achieve something like this
class Program
{
static void Main(string[] args)
{
Responsible responsible = new Responsible()
{
//I want here to populate with PopulatePerson the base members
Phone = "93827382",
Company = "Google"
};
}
public Person PopulatePerson(string pName, string pLastName)
{
Person person = new Person();
person.Name = pName;
person.LastName = pLastName;
return person;
}
}
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
public class Responsible : Person
{
public string Phone { get; set; }
public string Company { get; set; }
}
The case is more complex with database queries and stuff but basically this is what I need
I could use a member called Person in Responsible and do Person = PopulatePerson("Dan", "Johns") but since I'm inheriting I find it kinda redundant
What about something like this. I created a generic (static) factory method for Person that is reusable across all types that inherit from Person.
class Program
{
static void Main(string[] args)
{
//Responsible responsible = new Responsible()
//{
// //I want here to populate with PopulatePerson the base members
// Phone = "93827382",
// Company = "Google"
//};
var responsible = Responsible.Populate("Glenn", "Fake", "93827382", "Google");
//responsible
}
// NO LONGER NEEDED
// ============================
//public Person PopulatePerson(string pName, string pLastName)
//{
// Person person = new Person();
// person.Name = pName;
// person.LastName = pLastName;
// return person;
//}
}
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
public static TPerson Populate<TPerson>(string name, string lastname) where TPerson : Person, new()
{
TPerson person = new TPerson();
person.Name = name;
person.LastName = lastname;
return person;
}
}
public class Responsible : Person
{
public static Responsible Populate(string name, string lastname, string phone, string company)
{
var p = Responsible.Populate<Responsible>(name, lastname);
p.Phone = phone;
p.Company = company;
return p;
}
public string Phone { get; set; }
public string Company { get; set; }
}
Not sure if it makes sense your real scenario but you could change PopulatePerson to accept a Person object as an input parameter instead of internally creating a new one. Then you could pass your new Responsible object to it and afterwards set Phone and Company.
Edit: Like this
class Program
{
static void Main(string[] args)
{
Responsible responsible = new Responsible();
PopulatePerson(responsible, "first", "last");
responsible.Phone = "93827382";
responsible.Company = "Google";
}
public static void PopulatePerson(Person person, string pName, string pLastName)
{
person.Name = pName;
person.LastName = pLastName;
}
}
public class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
public class Responsible : Person
{
public string Phone { get; set; }
public string Company { get; 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.
I want to create a list of names and access it as a strongly typed enum. For eg.
string foo = FileName.Hello; //Returns "Hello.txt"
string foo1 = FileName.Bye; //Returns "GoodBye.doc"
Or it could be an object like:
Person p = PeopleList.Bill; //p.FirstName = "Bill", p.LastName = "Jobs"
How do I create a datatype like this?
Although the question is strange or not completely explained, here is the literal solution:
Option 1:
public static class FileName
{
public const string Hello = "Hello.txt";
public const string GoodBye= "GoodBye.doc";
}
Option 2:
public class Person
{
public string FirstName {get; set; }
public string LastName {get; set; }
public Person(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
}
public static class PeopleList
{
public static Person Bill = new Person("Bill", "Jobs");
}
just use a Dictionary<People, Person> for that:
enum People { Bill, Bob};
var myDict = new Dictionary<People, Person>();
myDict.Add(People.Bill, new Person() { FirstName = "Bill", LastName = "Jobs" });
now you can get Bill back with this syntax:
Person p = myDict[People.Bill];
You can you Extension Methods on your Enum object to return specific values.
Here's an article on CodeProject that will show you how to create an attribute that you can apply to each enumeration member to give it some "extra" data (like your filename, in this case) that you can use elsewhere in code.
You can use a struct (http://msdn.microsoft.com/en-us/library/ah19swz4(v=VS.100).aspx)
You can use static class with values..
public static class PeopleList
{
public static readonly Person Bill = new Person("Bill", "Jobs");
public static readonly Person Joe = new Person("Joe", "Doe");
}
public static class FileNames
{
public static readonly string Hello = "Hello.txt";
public static readonly string Bye = "Byte.txt";
}
then you can reference them as PeopleList.Bill or FileNames.Hello. It won't have the same properties as an enum and your methods will need to take a string or Person as parameter.
This is an over the top solution using attributes for your second example. Note this code has a lot of problems and is just an example.
public static T GetValue<T>(this Enum e) where T:class
{
FieldInfo fi = e.GetType().GetField(e.ToString());
var valueAttribute = fi.GetCustomAttributes(typeof (ValueAttribute),
false).FirstOrDefault() as ValueAttribute;
if (valueAttribute != null) return valueAttribute.Value as T;
return null;
}
class PersonValueAttribute : ValueAttribute
{
public PersonValueAttribute(string firstName, string lastName)
{
base.Value = new Person {FirstName = firstName, LastName = lastName};
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public static implicit operator Person(Enum e)
{
return e.GetValue<Person>();
}
}
enum PeopleList
{
[PersonValue("Steve", "Jobs")]
Steve
}
Allowing for simple usage:
Person steve = PeopleList.Steve;
Console.WriteLine(steve.FirstName); //Steve
I would use the Description attribute to attach custom data to an enum. Then you can use this method to return the value of the description:
public static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
string description = (attributes.Length > 0) ? attributes[0].Description : string.Empty;
return description;
}