Choose between property, method, extension method, toString for User.FullName

Suppose there is the following class:

public class User
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

I need to get the full name, I know the following ways how to do it:

1.Creating the required property in the class:

public string FullName
{
    get { return string.Format("{0} {1}", FirstName, LastName); }
}

2.Redefining ToString() for this class:

public override string ToString()
{
    return string.Format("{0} {1}", FirstName, LastName);
}

3.Creating an extension method:

public static UserHelpers
{
    public static string FullName(this User obj)
    {
        return string.Format("{0} {1}", obj.FirstName, obj.LastName);
    }
}

4.Creating a function

public string GetFullName()
{
    return string.Format("{0} {1}", FirstName, LastName);
}

I understand that the first two methods can only be used if it is possible to change the source class.

Explain please specify which method is preferable to use, the pros/cons of this or that method for further code maintenance.

Author: Kyubey, 2015-12-29

3 answers

The full name is a user property, and the fact that it is computable and not entered manually is just a convenience/inconvenience to use.

So, in terms of a class , this is its property. If the property should always be only computable (taking into account inheritance, yeah), then you can make a method out of the property.

ToString for complex objects, it is not very useful, although in this case it looks like something useful.

Extensions - only for other classes. Otherwise, follow them later it becomes too hard to follow and maintain.

UPD: for computable properties, you can make both properties and methods. I here rely more on how it behaves in the abstract case - it can be set manually in theory, or it is always a calculation from the properties of the entity. It should be borne in mind that no one usually writes more than a couple of lines to properties, i.e. as soon as your construction method increases to 5 lines , this is already an explicit candidate for the method. Well, it is worth considering that the property must be counted quickly, otherwise it is also an explicit method. The property should not explicitly make any requests to the server for information.

 5
Author: Monk, 2015-12-29 07:27:31

From my point of view, a computable field, with rare exceptions, is an entity external to the class. Therefore, finding such a field in the class is generally considered incorrect. Let me explain with an example: Let's say we have a class from the question:

public class User
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

We add a property(or a method-it doesn't matter):

public string FullName => LastName + FirstName;

All right, we're good. We release a product and forget about it. Ivan Petrov comes to the project, and they give him the task to write a certain feature where the output of the full name is required the user. Only in his case, he needs to output only the first name and the first part of the last name. He goes to the User class, looks at how it is done there, and decides to repeat the existing solution(he is right in some ways, - consistency is very important in the code). So it adds another property:

public string FullNameWithShortSecond => FirstName + LastName[0];

Do you think this is the end of our problems? Oh, no, they just started, because the salesmen pushed the sales of our wonderful software in the United States. Now the money will flow like a river! Here's just one bad thing - in the United States the order of First-Second[Name] is reversed in the Russian Federation. So we are creating another field, now for the US:

public string FullNameUsa => FirstName + LastName;

It is worth mentioning that usually there are not 2 properties in classes, and there can be dozens or even hundreds of variations of their comparisons. Will we all prescribe properties? Of course not. We will leave the minimum required interface of the class, but let the calculated fields be calculated by those who need them.

How will they implement calculated fields? This is not important, in C#, I think, the most a convenient way is to use extension methods. In C++, these will be free functions. Or you can create a decorator that will add calculated properties. But this is more complicated and not often necessary.


So, never add calculated fields to the original class? No, I'm not calling for that. I only encourage you to first consider how much this property is necessary for this class, and if you do not have a clear understanding of what this field should be exactly here, then it is not necessary to push it here. The class interface should be kept clean and tidy and not allowed to grow, simply because it seems that it will be easier to insert the field here.

 3
Author: ixSci, 2015-12-29 10:42:43

I would suggest a fourth option:

  1. Creating the GetFullName method in the class:

    public string GetFullName()
    {
      return string.Format("{0} {1}", FirstName, LastName);
    }
    

The first option (create the necessary property FullName in the class) not a bad option, although it's not so obvious to the users of your class that FullName changes when other properties change. As a rule, if you need to calculate something, it is better to make a method.


The second option (override ToString()) is suitable if you want to make a method that shows important human information, like

Console.Write("Кто я? Я " + me);

But if you want to create a way to get exactly the first and last name, this is not suitable:

string fullName = person.ToString();

How do we know that ToString() returns what we want, that is, "Ivan Prokofiev", and not "Ivan, 28 years old", or "Prokofiev Ivan Grigorevich, man #541"? The next option is more expressive:

string fullName = person.GetFullName();

It is better to use the third option only if necessary. If it is possible to modify the source class, it will be easier for everyone to put the methods in one class.

 2
Author: Peter Olson, 2015-12-29 06:41:43