My person class:
class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public int Age { get; private set; }
public Person(string firstName,string LastName,int age)
{
this.FirstName = firstName;
this.LastName = LastName;
this.Age = age;
}
public override string ToString()
{
return this.FirstName + " " + this.LastName + " " + this.Age;
}
}
Main:
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
}
}
Lets say I want to change the Firstname and Age of the person, how would I go about doing so? The FirstName and Age properties are set privately.
You could make the properties public -
class Person
{
// changed private set; to set;
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
So I just realized, all of the answers are assuming that the question you're asking is literally the question you're asking, rather than just an example. But perhaps you were just using it as an example, and you actually need to set a private property of an object that you don't control the source of? In which case, I would say, that's generally a bad idea, but if you really need to do it anyway, there is a way. That way is called "reflection" (this being just one of many kind-of-sketchy things you can do with reflection if you really want). This is a question that you might want to look at, if that is actually what you're after.
More likely, though, the correct response is just don't have the properties be private if you control the source for that class, and are going to want to change them.
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
sallyPerson = new Person("Newname", "Newvalue", 23);
}
}
This would be one way, another way would be to add methods in the Person object:
public void UpdateFirstName(string newName)
{
this.FirstName = newName;
}
and do sallyPerson.UpdateFirstName("newName");
Or make the properties public with public set and get
The class has been set up as Immutable meaning that once an instance of this class has been constructed it's properties cannot be modified. If you want to be able to construct this class and them modify it's properties you need to make the classes set properties to be public, like so:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
I'm hoping this is a homework question, otherwise #Brandon Cuff's answer is the obvious one.
Alternatively, you could expose methods to set the fields:
class Person
{
public void SetFirstName(string value)
{
this.FirstName = value;
}
}
Related
I am experimenting with classes and was wondering if it is possible to link classes depending on a boolean value within one of the classes. I have a Person class and a field is private 'boolean value HasPet'. So if a person has a pet then I would like for a pet object to be made and link the classes together. Is this possible. I am completely new to classes. Would I have to make an ID field and link them like that?
static void Main(string[] args)
{
Person Teacher = new Person("Phoebe", 32, "brown", "hazel", true);
}
public class Person
{
private string Name;
private int Age;
private string HairColour;
private string EyeColour;
private bool HasPet;
public Person(string name, int age, string hairColour, string eyeColour, bool hasPet)
{
Name = name;
Age = age;
HairColour = hairColour;
EyeColour = eyeColour;
HasPet = hasPet;
}
public void ChangePetStatus()
{
Console.Write($"We heard that your pet status has changed...");
if (HasPet == true)
{
Console.WriteLine("we are sorry to hear that. Pet status has been changed.");
HasPet = false;
}
else
{
Console.WriteLine("that's great. A pet is a lovely addition to the household. Pet status has been changed.");
HasPet = true;
}
}
public void Greetings()
{
Console.WriteLine($"Hello my name is {Name} and I am {Age} years old. I have {HairColour} hair and {EyeColour} eyes. It is {HasPet} that I have a pet.");
}
}
My suggestion would be to reevaluate what inheritance means, if we look into Microsoft's definition
Inheritance is one of the fundamental attributes of object-oriented
programming. It allows you to define a child class that reuses
(inherits), extends, or modifies the behavior of a parent class. The
class whose members are inherited is called the base class. The class
that inherits the members of the base class is called the derived
class.
In your case I would say that inheritance has nothing to do with Person and the referred Pet class as neither of them will be inheriting or reusing each other's members, if you or the task insists on using inheritance for this case you'll need some other class that groups Person and Pet by similar properties for example LivingBeing which could have functions Respire(), Move() etc..
I would say make a many to many relationship(or one to many, if it's a specific case and Pet can't have more than one Person as owner), where Person could have many Pets and Pet could have many Persons as owners.
classes which I would suggest are:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string HairColour { get; set; }
public string EyeColour { get; set; }
public IEnumerable<PersonPet> PersonPets { get; set; }
}
public class PersonPet
{
public int PersonId { get; set; }
public int PetId { get; set; }
}
public class Pet
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public IEnumerable<PersonPet> PetPersons { get; set; }
}
Where you would not need any inheritance or HasPet field as you can determine whether Person has a Pet or not by PersonPets.
EDIT:
As suggested in subcomments by #Ralf this is a relational view on current problem and classes could be subject to change. The main point is that, to link Person and Pet, using inheritance is not a right way. At least in the context which author provided
I need your help. I've got the following situation that I have a method with has to determine some conditions and depending on these conditions, returning an object of a specific type.
Now, I do not want to say public object methodXY() with object as return type but I have the approach which does not seem to work yet.
public T methodXY<T>()
{
if (condition A)
return (T)Convert.ChangeType(myValue, typeof(myType));
else if (condition B)
return (T)Convert.ChangeType(myValue, typeof(myOtherType));
else
throw new exception("xyz")
}
But with this, it seems that I have to set the return type already when calling the method. That's what I don't want and don't can.
//myType looks like this
public class myType
{
public string name;
public string firstname;
public string address;
}
and
//myOtherType looks like
public class myOtherType
{
public string name;
public string firstname;
}
Do you need more or more detailed information? Let me know.
Thanks in advance :-)
EDIT:
Here is the complete code sample of the method with object
public object myMethod(MyDto myDto)
{
userHasRoles = GetUserRoles();
if (userHasRoles .Contains("Admin"))
return (mapper.Map<myType>(myDto));
else if (userHasRoles.Contains("User"))
return (mapper.Map<myOtherType>(myDto));
throw new Exception("No elements!");
}
As far as I understand the problem, you need to return a more complete data when the retriever is the admin, and a not-so-complete one when not.
If that is the objective, then you can retrieve the appropriate data from the database and fill in an object of one of the following classes:
public class PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
}
public class ExtendedPersonData: PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address { get; private set; }
}
Since the latter class inherits from the former, you can just create a List<PersonData> and that will cover both cases.
Another, different approach: the data class takes into account the user in order to return or not certain data:
class Person {
public Person(User usr, string address)
{
this.User = usr;
this.address = address;
}
public string User { get; private set; }
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address {
get {
string toret = "N/A";
if ( this.User.IsAdmin() ) {
toret = this.address;
}
return toret;
}
}
private string address;
}
Neither of both solutions is perfect, and both have their own issues, but the problem, at least how you stated it, cannot be solved.
Hope this helps.
Is there a way to define my class so that callers of that class would get a compile time error unless they specified every property of the class, with the additional constraint that the parameters pass be named?
Let's say I have this interface:
public interface IPerson
{
string FirstName {get;}
string MiddleName { get; }
string LastName { get;}
}
And these classes:
public class PersonNeedAllProperties : IPerson
{
public string FirstName { get; private set;} // ideally readonly
public string MiddleName { get; private set;}
public string LastName { get; private set;}
public PersonNeedAllProperties(
string firstName,
string lastName,
string middleName)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
}
public class PersonCanNamePropertiesButNotSadlyNotRequired : IPerson
{
public string FirstName { get; set;} // ideally readonly
public string MiddleName { get; set;}
public string LastName { get; set;}
}
Then the problems with these imho are the following:
var p1 = new PersonNeedAllProperties("lastName", "firstName", "middle");
// woops wrong order because not named.
var p2 = new PersonCanNamePropertiesButNotSadlyNotRequired()
{
FirstName = "firstName",
LastName = "lastName"
}; // woops forgot all about the middlename.
Is there not a way to get a simple POCO object with an initalization similar to person two but that requires that all the properties be named?
Here is the fiddle of the above: https://dotnetfiddle.net/gUk8eT#
To answer your question No, this is not possible.
You ask to be able to force two things:
a) force all properties be set
b) force properties to be named.
These things can be done on their own but they cannot be combined because the methods for doing so are diametrically opposed as described below.
a) To force all properties be set you need to take them as inputs in a constructor.
b) To force properties to be set by name they cannot be specified in the constructor.
Side note: It is possible to provide named parameters to a constructor but it is not possible to force these i.e var person = new Person(firstName: 'John', lastName: 'Doe', middleName: 'A')
The closest you can get is to mark your properties readonly (private set) and have them only be set from within your constructor as you have done in your PersonNeedAllProperties class.
Something that might be a viable alternative is called the Builder Pattern.
This will have an extra class that is responsible for constructing your object, but you still wouldn't be able to get a compile time error, only runtime.
There's a horrible horrible way to almost enforce this. Not by name but by type. i'm not recommending it. but there is a horrible way to do it. did i mention it is horrible?
"any problem in computer science can be solved by adding another layer of indirection" - Wheeler?
Make each of the properties their own distinct type. now you can't pass them in the wrong order or the compiler will tell you that you passed an invalid type.
public class FirstName
{
string Value { get; set; }
}
public class MiddleName
{
string Value { get; set; }
}
public class LastName
{
string Value { get; set; }
}
public interface IPerson
{
FirstName FirstName {get;}
MiddleName MiddleName { get; }
LastName LastName { get;}
}
public class PersonNeedAllProperties : IPerson
{
public FirstName FirstName { get; private set;} // ideally readonly
public MiddleName MiddleName { get; private set;}
public LastName LastName { get; private set;}
public PersonNeedAllProperties(
FirstName firstName,
MiddleName lastName,
LastName middleName)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
}
This can be achieved with a nested class I guess:
public interface IPerson
{
string FirstName { get; }
string MiddleName { get; }
string LastName { get; }
}
public class Person : IPerson
{
public string FirstName { get; private set; }
public string MiddleName { get; private set; }
public string LastName { get; private set; }
//Make sure the parameterless constructor is private
private Person() { }
private Person(string first, string middle, string last)
{
this.FirstName = first;
this.MiddleName = middle;
this.LastName = last;
}
public class Builder
{
private Person person = new Person();
public Builder WithFirstName(string first)
{
person.FirstName = first;
return this;
}
public Builder WithMiddleName(string middle)
{
person.MiddleName = middle;
return this;
}
public Builder WithLastName(string last)
{
person.LastName = last;
return this;
}
public IPerson Build()
{
if (person.FirstName != null
&& person.MiddleName != null
&& person.LastName != null)
return person;
throw new Exception("Cannot build person because reasons...");
}
}
}
Then use it as follows:
var person = new Person.Builder()
.WithFirstName("Rob")
.WithMiddleName("<I have no middle name>")
.WithLastName("Janssen")
.Build();
You can use the With... methods in any order you like:
var person = new Person.Builder()
.WithLastName("Janssen")
.WithFirstName("Rob")
.WithMiddleName("<I have no middle name>")
.Build();
Fiddle here
Edit: Crap; I din't notice the other requirement of compile time errors.
This does, however, 'force' you to set all 3 required fields and 'forces' you to "name" the field using the With... methods which makes it hard to confuse the values and also allows you to specify the values in the order you desire. It also prevents you from instantiating a Person yourself and also allows you to have your private setters (e.g. 'read only' properties) and keeps your interface intact. The only thing missing here is compile time errors; you won't get one here. Maybe Code Contracts can help in that department, but that would at least require some 'team coordination' (e.g. everyone needs to install an extension and have static checking enabled); and I'm not 100% sure if it can be done with code contracts either.
No, interfaces aren't designed to behave that way.
An interface assure you that the classes who implements it will have all the elements declared in the interface. But doesn't make any statements on how they are going to be implemented.
You can accomplish what you want with an abstract class with a custom constructor.
public abstract class Person
{
public abstract string FirstName {get; protected set; }
public abstract string MiddleName { get; protected set; }
public abstract string LastName { get; protected set; }
public Person(string firstName, string middleName, string lastName){
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
}
}
public class PersonNeedAllProperties : Person
{
public override string FirstName{get; protected set;}
public override string MiddleName{get; protected set;}
public override string LastName{get; protected set;}
public PersonNeedAllProperties(
string firstName,
string lastName,
string middleName)
: base(firstName, lastName, middleName)
{
}
}
The custom constructor force you to complete the names in the child classes.
You can combine this answer with the one of John Gardner using classes instead of strings for the names (firstName, middleName, lastName) to simulate the named parameters.
You need to be aware of the limitations of this method, in C# you cannot inherit from more than one class, so you need to keep this restriction in mind if you decide to implement this solution.
I have a base class with three field, but instead of initializing its field the normal way like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
public ParentClass(string Name, string Family, string Address)
{
this.Name = Name;
this.Family = Family;
this.Address = Address;
}
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(string Name, string Family, string Address, int StudentID, int StudentScore)
: base(Name, Family, Address)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass("John", "Greene", "45 Street", 76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I’ve initialized the fields in the ChildClass constructor without explicitly calling the base class constructor like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(int StudentID, int StudentScore)
{
Name = "John";
Family = "Greene";
Address = "45 Street";
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass(76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I know I could have initialized the parent class’s field in the parent class itself and this is a bogus example, but I was wondering if it is considered a good practice to do something like that in real life and more complex situations, is there any reason why I shouldn’t do something like this? as to not explicitly call the base class constructor?
Edit: I'm more concerned about not explicitly call the base class constructor and initializing it in subclass part, so I've edited the last part that mentioned the fields being exposed out.
As you've already seen, the fields are already "exposed". Your could still get to those variables from the derived class in the first example.
As to not using a base class constructor being good practice, I would say not. By only having a parameterized base class constructor, you are making sure that future implementers of that class initialize the base class properties. For example, in your second I could write:
public ChildClass(int StudentID, int StudentScore)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
With no errors. Other than that there are very few differences between your samples.
Imagine, there are 3 projects.
A library, and 2 executables.
Both programs use the library.
Project 1, creates many instances of classes inside there, saves them with a serializer.
Project 2, loads them, but should NEVER make any changes on them.
So, it should be read-only for project 2, but project 1 should have full access to it.
How do I design that?
Lets say, there is this class in the library:
public string Name { get; private set;}
public int Age { get; private set;}
public Person(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
}
This would be perfect for project 2, who uses it as a read only.
But very annoying for project 1, because as soon it as to change just one property in the class, it has to create an entire new instance. Not annoying when having 2 properties, but very annoying when having like 10 properties.
Project 2 even would be happy when these values are const.
What's the best way to design that?
Interface are the way to do things like that.
public IPerson
{
string Name { get; }
int Age { get; }
}
In Project1 :
public class Person : IPerson
{
public string Name { get; set;}
public int Age { get; set;}
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
In Project2:
public class Person : IPerson
{
public readonly string _name;
public string Name { get { return _name; } }
private readonly int _age;
public int Age { get { return _age; } }
public Person(string name, int age)
{
this._name = name;
this._age = age;
}
}
Note that true immutable class use readonly field instead of private setter.
A private setter allow the instance to modifiy his state after his creation, and so it is not a truly immutable instance.
Whereas a reaonly field can be set in constructor only.
Then you can have same methods sharing via extensions:
public static class PersonExtensions
{
public static string WhoAreYou(this IPerson person)
{
return "My name is " + person.Name + " and I'm " + person.Age + " years old.";
}
}
Conditional compiling could do it, simply create new build configurations in Visual Studio and use a conditional compilation symbol, then wrap all the writable statements so they get compiled with one configuration but not the other, for example:
public string Name {
get;
#if WriteSupport
private set;
#endif
}
public int Age {
get;
#if WriteSupport
private set;
#endif
}
public Person(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
}