5
\$\begingroup\$

Generally speaking, I try and write my classes so they are highly cohesive.

Sometimes I have accessors (this problem isn't limited to accessors) which derive their value from non-public data only, which lowers cohesion. (http://www.ndepend.com/metrics.aspx#LCOM)

Take the following class example:

public class Person
{
    public DateTime Birth { get; set; }
    public DateTime? Death { get; set; }

    public double Age 
    {
        get 
        {
            return (Death ?? DateTime.Now - Birth).TotalDays / 365;
        }
    }
}

Ignoring the probable compile errors and lack of error checking, Age could easily be an extension method GetAge as it doesn't rely on non-public data.

The code would look as follows:

public class Person
{
    public DateTime Birth { get; set; }
    public DateTime? Death { get; set; }
}

public static class PersonExtensions
{
    public static double GetAge(this Person person)
    {
        return (person.Death ?? DateTime.Now - person.Birth).TotalDays / 365;
    }
}

What is a good approach to determine whether something should be an extension method or implemented in the class itself?

Some arguments against doing this that I find extension methods have lower visibility, you have to know the extension exists, while if it was a class property its existence would be obvious.

For languages that don't use extension methods (C++, php, etc.) the extension method could be written as a static method which accepts a Person as it's parameter.

\$\endgroup\$
  • 2
    \$\begingroup\$ I'm not a fan of that property/method since it calls DateTime.Now. I'd rather pass in a DateTime. \$\endgroup\$ – CodesInChaos Apr 12 '13 at 10:17
  • \$\begingroup\$ Also, if the class is generated by some tool, it would be convenient to use extension methods. \$\endgroup\$ – Babu James Aug 21 '14 at 9:53
  • \$\begingroup\$ A year has 365 days and a quarter I think. I'm not sure this can cause a problem in your code though.. \$\endgroup\$ – IEatBagels Aug 21 '14 at 12:59
11
\$\begingroup\$

My personal view is create an extension method if:

  • The class/interface you wish to extend is not created by you.
  • The class/interface is created by you but the behavior of the extension method is only required in an assembly that doesn't contain the class (e.g. class Person is defined in MyApp.dll, but GetAge() is only required in MyApp.UI.exe).
  • The behavior can be defined against a more generic abstraction than the class itself where the implementation is the same but the classes don't share a common base. e.g. create an ILifeSpan interface with DateTime DateOfBirth and DateTime DateOfDeath properties and create the extension method public static double GetAge(this ILifeSpan lifeSpan)

FYI extension methods are just a compiler trick, the generated IL just calls the static method, the this keyword just allows you to write less code in visual studio.

when you call person.GetAge();, it is compiled to PersonExtensions.GetAge(person);

\$\endgroup\$
0
\$\begingroup\$

Maybe a god approach would be to use extension method when you would duplicate data if you would put another property or method into your class.

In your example you would do that: storing (i know you don't store both of them) the date of birth and the age is redundant.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.