What to pass? Reference Object or Value Type?
Guys I have a "best practice question" For example I have this classes:
class Person
{
public int age {get; set;}
}
class Computer
{
public void checkAge(开发者_运维问答Person p) // Which one is recommended THIS
{
// Do smthg with the AGE
}
public void checkAge(int p) // OR THIS
{
//Do smthg with the age.
}
}
What is recommended to pass? Just what I need (int-value type) or the whole object (reference type)
Im asking this because Im using LINQ on an app that I am making and I have created many entities where I should pass the IDs (foreing keys), but Im passing objects.
What is the best approach?
The function checkAge
should only take in the minimum amount of information needed to perform it's job. Adding anything else just creates an artificial dependency. If only an int
is needed then that is the solution I should take.
I would argue that in this case, the answer is probably neither. Either "Age" would be factored out into its own class, or if the operation is context-specific with Person, it would be found inside the Person class itself.
with the information given, neither solution is good
the first solution requires the Computer class to know about Person.Age, for no apparent reason
the second attaches a method to the Computer class that has nothing to do with the properties of the Computer object
some context would be helpful - if this is a validation, then CheckAge belongs to the Person class (with possibly an IsAgeAcceptable property)
Why is the Computer checking the age of a Person? The answer to this determines what makes sense...
Follow the law of demeter for functions. Basically the law states that entities should be loosely coupled. Ask yourself the following question, should a computer object know about a person object? In this case, maybe all you are doing inside checkAge is checking an int value. If that is the case then what makes you think passing the entire object is needed? Simply pass the person age and take it in as an int in this case.
So prefer
public void checkAge(int n)
I would like to point out that when passing a reference, the reference is a 32 bit integer while a data type is copied. So if your value type is larger that a 32bit int, pass by reference if performance or memory is any sort of issue.
I'd point out that int Age
is probably not the best way to store that value.
(Why is DateTime a Property and not a Method
)
class Person : IBorn
{
public DateTime Birth {get; set;}
}
interface IBorn
{
DateTime Birth {get; set;}
}
interface IDateTimeFactory
{
DateTime Now();
}
class DefaultDateTimeFactory : IDateTimeFactory
{
public DateTime Now()
{
return DateTime.Now;
}
}
public static class IBornExtensions
{
public TimeSpan AgeFromNow(this IBorn birthed, IDateTimeFactory dtf)
{
return dtf.Now() - birthed.Birth;
}
public TimeSpan AgeFrom(this IBorn birthed, DateTime from)
{
return from - birthed.Birth;
}
}
class Computer
{
public void checkAge(IBorn birthed)
{
var age = birthed.Age((new DefaultDateTimeFactory()).Now());
}
}
I'm sure someone out there is thinking, "thats a lot of code for this answer, sure seems outrageous". Well like how DateTime.Now
should have been a method (because methods return values that could change per call, and property should normally not change values per call, see the link above), Age changes per call, so the Property should probably be Birth. Next I encapsulated the method of determining Age as an Extension method because anything that can be IBorn
certainly can have an Age (ignore the philosophical question of something is dead, does it have an Age :P). And lastly, created the IDateTimeFactory
object so one can unit test the Age method to determine if it's calculating age correctly (otherwise, hardcoding DateTime.Now
means you can't tell how old something is say compared to something else e.g old is my brother compared to my sister).
精彩评论