I have the following class:
public class Person
{
public String Name { get; set; }
}
I have a method that takes in Person and a String as parameters:
public void ChangeName(Person p, String name)
{
p.Name = name;
}
Since Person was passed by reference, it should change the Name of the passed instance.
But is this method more readable than the one above?
public Person ChangeName(Person p, String name)
{
p.Name = name;
return p;
}
Is it more readable? No. In fact you may be doing more harm them good.
By having it return a Person object, it might lead you to believe that instead of modifying the Person parameter, it is actually creating a new Person based on p but with a different name and someone could incorrectly assume that p is never changed.
Either way, if you have a method that has no affect on the class it is apart of it should probably be static. That helps you know for sure that it doesn't affect its class. Only have the method return a value if you need it to return a value.
So here is my recommendation for this method:
public static void ChangeName(Person p, String name)
{
p.Name = name;
}
There isn't anything right/wrong with either approach. Depends on what your program needs.
Returning the parameter passed into a method is rarely needed as it is always possible for the user to just use the variable passed as argument instead.
It, however, gives you the flexibility of eventually overriding this implementation, or passing this implementation into another function which accepts delegates with similar signatures. Then you can pass in other implementations that does not return the same Person object.
Do it only if you really need the flexibility.
I would suggest you use one of the following for best readability:
public static void ChangeName(Person p, String name)
{
p.Name = name;
}
public static Person WithName(Person p, String name)
{
return new Person(p) { Name = name };
}
The second one treats the Person object as immutable and does not change the state of the object. The ChangeName function explicitly changes the state of the input object. I think it's important to make a clear distinction between the two types of methods. A good rule of thumb to follow is that a method should not change the state of an object AND return one at the same time.
first of all p is not being passed by reference in the first example. Your second method makes one believe that it is returning a new reference which it is not. So I don't think the second one is any clearer than the first one.
In the case you've described, I would say neither. Its not really clear what you are trying to do with this method. Just use the object and set the property. Inserting a method into the execution path just complicates understanding and creates another dependency on the Person object and its underlying value.
If you are asking a meta question that involves some design over and above the code you have posted, then I am missing it.
The first one is better, because of that the second one might lead you to believe that p is immutable.
But, the whole method is useless since it just calls the setter. Why not just call the setter directly?
I beleve that your 2nd approach is not more readable YAGNI. But if you change it like this
public static class PersonExtensions
{
public static Person ChangeName(this Person p, String name)
{
p.Name = name;
return p;
}
you will have an extensionmethod for a fluent interface a la
new Person().ChangeName("Peter Smith").SendEmail().Subject("Test Mail").Receiver("....)
Here is the definitive reference to understand passing parameters by value/reference.
Looking at the code, why don't you use property?
public string Name
{
set {name = value;}
get { return name; }
}
EDIT: Auto implemented properties
public string Name
{
set;
get;
}
Related
This seems to be very stupid and rudimentary question, but i tried to google it, but couldn't a find a satisfactory answer,
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(){}
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Other properties, methods, events...
}
My question is if i have class like this, what is the best way to create an object?
Person p=new Person("abc",15)
OR
Person p=new Person();
p.Name="abc";
p.Age=15;
What is the difference between these two methods and what is the best way to create objects?
Decide if you need an immutable object or not.
If you put public properties in your class, the state of every instance can be changed at every time in your code. So your class could be like this:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(){}
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Other properties, methods, events...
}
In that case, having a Person(string name, int age) constructor is not so useful.
The second option is to implement an immutable type. For example:
public class Person
{
public string Name { get; private set; }
public int Age { get; private set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Other properties, methods, events...
}
Now you have a constructor that sets the state for the instance, once, at creation time. Note that now setters for properties are private, so you can't change the state after your object is instantiated.
A best practice is to define classes as immutable every time if possible. To understand advantages of immutable classes I suggest you read this article.
Really depends on your requirement, although lately I have seen a trend for classes with at least one bare constructor defined.
The upside of posting your parameters in via constructor is that you know those values can be relied on after instantiation. The downside is that you'll need to put more work in with any library that expects to be able to create objects with a bare constructor.
My personal preference is to go with a bare constructor and set any properties as part of the declaration.
Person p=new Person()
{
Name = "Han Solo",
Age = 39
};
This gets around the "class lacks bare constructor" problem, plus reduces maintenance ( I can set more things without changing the constructor ).
There's not really a best way. Both are quite the same, unless you want to do some additional processing using the parameters passed to the constructor during initialization or if you want to ensure a coherent state just after calling the constructor. If it is the case, prefer the first one.
But for readability/maintainability reasons, avoid creating constructors with too many parameters.
In this case, both will do.
In my humble opinion, this is just a matter of deciding if the arguments are optional or not. If an Person object shouldn't (logically) exist without Name and Age, they should be mandatory in the constructor. If they are optional, (i.e. their absence is not a threat to the good functioning of the object), use the setters.
Here's a quote from Symfony's docs on constructor injection:
There are several advantages to using constructor injection:
If the dependency is a requirement and the class cannot work without it then injecting it via the constructor ensures it is present when the class is used as the class cannot be constructed without it.
The constructor is only ever called once when the object is created, so you can be sure that the dependency will not change during the object's lifetime.
These advantages do mean that constructor injection is not suitable for working with optional dependencies. It is also more difficult to use in combination with class hierarchies: if a class uses constructor injection then extending it and overriding the constructor becomes problematic.
(Symfony is one of the most popular and respected php frameworks)
If you think less code means more efficient, so using construct function is better.
You also can use code like:
Person p=new Person(){
Name='abc',
Age=15
}
how about
var obj = new {ID = 1, Price = 2};
Depends on your requirment, but the most effective way to create is:
Product obj = new Product
{
ID = 21,
Price = 200,
Category = "XY",
Name = "SKR",
};
Or you can use a data file to put many person objects in to a list or array. You do need to use the System.IO for this. And you need a data file which contains all the information about the objects.
A method for it would look something like this:
static void ReadFile()
{
using(StreamWriter writer = new StreamWriter(#"Data.csv"))
{
string line = null;
line = reader.ReadLine();
while(null!= (line = reader.ReadLine())
{
string[] values = line.Split(',');
string name = values[0];
int age = int.Parse(values[1]);
}
Person person = new Person(name, age);
}
}
I have some data which I need to pass on to a recursive function. I want to make sure it isn't changed within that function. How can I do this?
Consider:
static List<Person> GetPeopleWithSameNameAncestors(List<Person> people)
{
return people.Where(person => HasAncestorWithName(person.Parents, person.Name)).ToList();
}
//Here, nameToLookFor is always the same for every outside call to this function
static bool HasAncestorWithName(List<Person> lookIn, String nameToLookFor)
{
return lookIn.Any(p => p.Name == nameToLookFor || (p.Parents != null && HasAncestorWithName(p.Parents, nameToLookFor)));
}
Real situation is more complicated, that's why it's important to make sure nameToLookFor isn't changed, because somebody could easily do that. Oh, and I can't touch the "Person" class.
If this isn't possible directly, does anybody know a pattern which could solve this problem safely?
If you are really worried about this, consider using the Decorator Pattern to wrap your Person object - but wrap it, as to make it Immutable.
public class PersonWrapper()
{
Person p;
public PersonWrapper(Person person)
{
prop = person;
}
Public string Name
{
get { return p.Name; }
}
}
Pass this object around in your code - you can easily convert the list like:
var immutablePersonList = personList.Select(p => new PersonWrapper(p));
Also, use Immutable collection types, like IEnumerable instead of mutable ICollection implementations.
Maybe I am overlooking something obvious, but I have seen in code where you may have a property like "HairColor", and then a method like "HairColor.Update()". Is this possible?
Person person = new Person(int personID);
person.HairColor = "Blonde";
person.HairColor.Update();
I have specific properties that I want to be able to extend on a case by case basis. I guess I could have a method called "HairColorUpdate", but seems that HairColor.Update() should be possible. I don't want to use "set" because I don't always want to update the DB this way.
The reason I am doing this is because I may only want to call the database to update one column instead of calling my save method which updates every column hopefully improving efficiency.
person.HairColor.Update() just means that the type returned by the HairColor property has a method called Update. In your example it looks like HairColor is a string, so to achieve that you need to implement an extension method for string. E.g. something like
static class StringExtension
{
public static void Update(this string s)
{
// whatever
}
}
However, I don't see the point of doing this. The Update method is a static method that works on the string, so it doesn't affect the Person instance. (even if string did have an Update method it would be unrelated to the Person type).
I believe you would want to have the Update method on Person instead as others have pointed out.
That is not possible, unless the return value of HairColor has an Update() method. Another way to do this is to have
Person person = new Person(int personID);
person.HairColor = "Blonde";
person.Update();
Where the update method checks to see which fields have been updated and then updates the database based on that information.
HairColor would probably have to be a struct type to make what you want to work. Plus, you would have to do operator overloading. I'm not sure if this is truly the design path you want to pursue. If, for some perverse reason, you absolutely must do it, this is the kind of struct definition you would need (very roughly, LOL):
public struct HairColorStruct
{
private string m_hairColor;
public void Update()
{
// do whatever you need to do here...
}
// the very basic operator overloads that you would need...
public static implicit operator HairColorStruct(string color)
{
var result = new HairColorStruct();
result.m_hairColor = color;
return result;
}
public static explicit operator string(HairColorStruct hc)
{
return hc.m_hairColor;
}
public override string ToString()
{
return m_hairColor;
}
public static bool operator ==(HairColorStruct from, HairColorStruct to)
{
return from.m_hairColor == to.m_hairColor;
}
public static bool operator ==(HairColorStruct from, string to)
{
return from.m_hairColor == to;
}
public static bool operator !=(HairColorStruct from, HairColorStruct to)
{
return from.m_hairColor != to.m_hairColor;
}
public static bool operator !=(HairColorStruct from, string to)
{
return from.m_hairColor != to;
}
}
You can then redefine your Person object like this:
public class Person
{
public HairColorStruct HairColor { get; set; }
// whatever else goes here...
}
In your code, HairColor can be simply assigned whatever you desire as long as it's a string:
var person = new Person();
person.HairColor = "Blonde";
// this will emit "True" to the console...
if (person.HairColor == "Blonde")
{
Console.WriteLine(true);
}
else
{
Console.WriteLine(false);
}
// update the info per your logic...
person.HairColor.Update();
// you can change the hair color and update again, LOL
person.HairColor = "Brown";
person.HairColor.Update();
It's not a property with a method, but type returned by the property has that method declared inside. So you use a property and within returned value, which is the type, call the method.
I think you need Update method on the Person class, not Update method on string:
Person person = new Person(int personID);
person.HairColor = "Blonde";
// set other properties
person.Update();
Actually mixing business logic of person class and database-related logic is rarely good idea. So, I'd go to something like:
dbSession.SaveOrUpdate(person); // NHibernate
Or even extension method:
public static void Update(this Person person)
{
// connect to database and do update query
}
Couldn't you just do:
public class HairColor : String
{
private int _personID;
public HairColor(int personID)
{
_personID = personID;
}
public void Update()
{
//update the database here for hair color
}
}
This way you can have more control with specific functionality. Remember, class responsibility.
This solution is only if you really want to update one column of course.
Hope that helps.
1) I'm still quite new to programming and have read a bit about getters and setters. But I really don't understand why they are used.. Could anyone explain it, or point me to an article? (The ones I read were not really understandable for me...)
2) In my current project I have a class where I declare and initialize an array of structs. I now need to access the array from another class, but it gives me the error: An object reference is required to access non-static member 'BaseCharacter.Attributes'.
I figures this could mean I need to use getters and setters? But how does this work for arrays?
Thanks in advance!
Simon.
EDIT: 2nd question got solved, which brings me to something else. When I want to use some class in another one, I'm making a new instance of the class, right? And this means I get the original values?
But that's not what I want.
The second class is used to generate the UI, and needs the values I'm keeping in the first class.
At some point I will implement save files (XML or even on a server in later stage). Can I then just get the values from those files?
For the getters and setters (the things that use them are called Properties) it's just a convenient and nice-looking way to make people think they're using a variable, but to do some computation whenever the variable is updated or accessed. For instance:
BankAccount.Interest
looks better than
BankAccount.GetInterest()
Even though you can calculate the interest at the time it is requested in both cases.
They are also used to make a variable be able to be accessed from outside the class, but changeable only from within the class with this technique:
public double Interest {
get;
private set;
}
For an example of a setter being used, if you've ever used Windows Forms and updated a control's Height or Width property, you're using a setter. While it looks like you're using a normal instance variable like c.Height = 400, you're really letting c update it's position by redrawing at a new place. So setters notify you exactly when a variable is changed, so your class can update other things base on the new value.
Yet another application of Properties is that you can check the value people try to set the property to. For instance, if you want to maintain an interest rate for each bank account but you don't want to allow negative numbers or numbers over 50, you just use a setter:
private int _interestRate = someDefault;
public int InterestRate {
get { return _interestRate; }
set {
if (value < 0 || value > 50)
throw new SomeException(); // or just don't update _interestRate
_interestRate = value;
}
}
This way people can't set public values to invalid values.
For your second question, you can do one of two things depending on what you're trying to do.
One: You can make that member static. That means that just one of them exists for the entire class instead of one per instance of the class. Then you can access it by ClassName.MemberName.
You can do that this way:
// inside the BaseCharacter class definition:
public static SomeStruct[] Attributes = new SomeStruct[size];
// then to use it somewhere else in your code, do something with
BaseCharacter.Attributes[index]
Two: You have to make an instance of the class and access the array through that. This means that each object will have its own seperate array.
You'd do that like this:
BaseCharacter bc = new BaseCharacter();
// use bc.Attributes
The second one is probably what you'll want to do, since you probably will want to modify each character's attributes seperately from all the other characters.
Actually the error you mention is not related to the getters and setters concept, it's because after creating your class you need to create an object before using its members; think of the class as a template for a document and the object as the document
you are most likely doing something like this:
var someVar = BaseCharacter.Attributes;
When you should be doing something like this:
var someVar = new BaseCharacter();
var someOtherVar = someVar.Attributes;
And about why the getters and setters, Seth Carnegie's Answer covers it nicely.
If you are new to Object Oriented Programming, you may be missing an important concept, that is about encapsulation.
Fields (attributes) of a class should be accessed only from within the class (or it's inherited classes). That is, if we have a class person, only with a name, you can do
public class Person
{
public string Name;
}
So anywhere in your program, you will be able to access it by doing:
Person person = new Person();
person.Name = "Andre";
This works, but it's not encapsulated. In some languages like C++ or Java, it was done like this:
public class Person
{
private string _name;
public string setName(string newName)
{
this._name = newName;
}
public string getName()
{
return this._name;
}
}
Person person = new Person();
person.setName("Andre");
This makes our _name attribute encapsulated, it can only be retrieved by it's get and set methods (that is, by the interface of the class).
C# makes this easier, allowing getters and setters:
public class Person
{
private string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
Person person = new Person();
person.Name = "Andre";
This is very much like the second example (Java/C++ way), but you treat Name as property, instead of methods, and leaving our name property encapsulated
1) They might seem optional but they allow you more control over code:
You're able to intercept new values and avoid them being set (e.g. to exclude pointless values). Also you're able to fire custom events in case a property is changed or updated (just like the WinForms controls do).
private string name;
public string Name
{
get
{
// running additional code, e.g. here I avoid returning 'null' for a name not set
if(name == null)
return "(Unknown)";
return name;
}
set
{
// checking incoming values, e.g. here I avoid setting an empty name
name = value != null && value.Length > 0 ? name : null;
// running more/additional code, e.g. here I raise an event
if(OnNameChange)
OnNameChange();
}
}
2) Without knowing the code it's hard to tell you the exact reason, but if you'd like to access some member variable or property you have to either create an object of that class or make the variable static (e.g. shared between all instances of the object):
class MyClass
{
public static int someNumber = 55;
public int thisNumber;
}
// ...
int someothervar = MyClass.someNumber; // access the static member variable
MyClass mc = new MyClass(); // create an object of the class
int yetanothervar = mc.thisNumber; // access the member variable
This might seem like a CS101 question, but I've managed to thoroughly confuse myself.
//this is inside a service class
ObjectToUpdate objectToUpdate = objectrepository.Get(objectToUpdate.Id);
SecondObject secondObject = secondObjectRepository.Get(secondObject.Id);
objectToUpdate.Update(secondObject);
objectRepository.Save(objectToUpdate);
//the object itself
public class ObjectToUpdate {
public int Id { get; set; }
public string Name { get; set; }
public void Update(SecondObject secondObject) {
Name = secondObject.Name
}
}
When I get to the "Save" line, it will correctly have updated the objectToUpdate with the name from the secondObject, correct? It carries a reference to itself when you pass it to the Update method?
Yes, classes are passed around by reference, so you will be passing a reference to the same object. This tutorial provides a great reference for understanding this concept: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91&PagePath=/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx
That looks correct to me. When you get to the Save() line, objectToUpdate.Name will be the same as secondObject.Name
If it is easier to read logically, you could change this line to include "this."
this.Name = secondObject.Name
so that you realize that the Name property being set is the one that belongs to 'this' which is the same object instance that the method was called on. The code is functionally identical, but might be easier to comprehend?
Yes, the value of a .NET Object is actually the memory address where that object is stored. Saying firstObject = secondObject wouldn't affect the secondObject referenced in the calling method, but saying firstObject.Name = secondObject.Name will change the value of the Name.