Question

Si je construis une chaîne à l'aide d'un objet StringBuilder dans une méthode, cela aurait-il un sens de:

Renvoyez l'objet StringBuilder et laissez le code appelant appeler ToString ()?

return sb;

OU Renvoyez la chaîne en appelant moi-même ToString ().

return sb.ToString();

Je suppose que cela fait une différence si nous retournons des chaînes de petite ou grande taille. Qu'est-ce qui serait approprié dans chaque cas? Merci d'avance.

Modifier: Je ne prévois pas de modifier davantage la chaîne dans le code d'appel, mais bon point, Colin Burnett.

Principalement, est-il plus efficace de renvoyer l'objet StringBuilder ou la chaîne? Une référence à la chaîne serait-elle renvoyée ou une copie?

Était-ce utile?

La solution

Renvoyez le StringBuilder si vous envisagez de modifier davantage la chaîne. Sinon, renvoyez la chaîne. Ceci est une question de l'API.

En ce qui concerne l'efficacité. Puisqu'il s'agit d'une question vague / générale sans précision, je pense que le terme mutable ou immuable est plus important que la performance. La mutabilité est un problème d'API permettant à votre API de renvoyer des objets modifiables. La longueur de la chaîne est sans importance pour cela.

Cela dit. Si vous regardez StringBuilder.ToString avec Reflector:

public override string ToString()
{
    string stringValue = this.m_StringValue;
    if (this.m_currentThread != Thread.InternalGetCurrentThread())
    {
        return string.InternalCopy(stringValue);
    }
    if ((2 * stringValue.Length) < stringValue.ArrayLength)
    {
        return string.InternalCopy(stringValue);
    }
    stringValue.ClearPostNullChar();
    this.m_currentThread = IntPtr.Zero;
    return stringValue;
}

Vous pouvez voir que cela peut faire une copie, mais si vous le modifiez avec StringBuilder, il en fera une copie ensuite (c’est ce que je peux dire du point de fil actuel).

Je suppose que la fin de ceci est que si vous ne modifiez pas StringBuilder, vous ne copiez pas la chaîne et la longueur n'a aucune incidence sur l'efficacité (à moins que vous ne touchiez ce 2e si).

MISE À JOUR

System.String est une classe qui signifie qu'il s'agit d'un type de référence (par opposition au type de valeur), donc "chaîne foo;". est essentiellement un pointeur. (Lorsque vous transmettez une chaîne à une méthode, il transmet le pointeur et non une copie.) System.String est modifiable à l'intérieur de mscorlib mais immuable à l'extérieur, ce qui permet à StringBuilder de manipuler une chaîne.

Ainsi, lorsque ToString () est appelée, elle renvoie son objet chaîne interne par référence. À ce stade, vous ne pouvez pas le modifier car votre code n'est pas dans mscorlib. En définissant le champ m_currentThread sur zéro, toute opération ultérieure sur StringBuilder le fera copier l'objet chaîne afin qu'il puisse être modifié et ne modifie pas l'objet chaîne renvoyé dans ToString (). Considérez ceci:

StringBuilder sb = new StringBuilder();
sb.Append("Hello ");

string foo = sb.ToString();

sb.Append("World");

string bar = sb.ToString();

Si StringBuilder n'a pas fait de copie, à la fin, foo serait "Hello World". parce que StringBuilder l'a modifié. Mais comme il en a fait une copie, alors foo est toujours juste "Bonjour". et bar est "Hello World".

Est-ce que cela clarifie l'ensemble du retour / référence?

Autres conseils

Je ne pense pas que la performance devrait être un facteur dans cette question. De toute façon, quelqu'un appellera sb.ToString () pour que vous puissiez prendre le hit quelque part.

La question la plus importante est de savoir quelle est l’intention de la méthode et le but recherché. Si cette méthode fait partie d'un générateur, vous pouvez renvoyer le générateur de chaînes. Sinon, je retournerais une chaîne.

Si cela fait partie d'une API publique, je voudrais plutôt retourner une chaîne au lieu du constructeur.

Je dirais que la méthode devrait renvoyer sb.ToString (). Si la logique entourant la création de l'objet StringBuilder () devait changer à l'avenir, il me semble logique de la modifier dans la méthode, pas dans chaque scénario qui appelle la méthode, puis continue à faire autre chose

StringBuilder est un détail d'implémentation de votre méthode. Vous devez renvoyer une chaîne jusqu'à ce que cela devienne un problème de performances. Vous devrez alors explorer un autre modèle (comme modèle du visiteur ) qui peut vous aider à introduire l’indirection et vous protéger des décisions d’implémentation internes.

Les chaînes sont toujours stockées dans le tas, vous aurez donc une référence renvoyée si le type de retour est string. Cependant, vous ne pouvez pas compter sur deux chaînes identiques pour avoir des références identiques. En général, il est prudent de penser à une chaîne comme s’il s’agissait d’un type de valeur même s’il s’agit en réalité d’un type de référence.

Je pense que cela dépend de ce que vous faites avec la chaîne une fois qu'elle quitte la méthode. Si vous souhaitez continuer à l'ajouter, vous pouvez envisager de renvoyer un constructeur de chaînes pour une plus grande efficacité. Si vous appelez toujours .ToString () dessus, vous devriez le faire dans la méthode pour une meilleure encapsulation.

Je retournerais une chaîne dans presque toutes les situations, en particulier si la méthode fait partie d'une API publique.

Une exception serait si votre méthode n'est qu'une partie d'un "constructeur" privé plus grand et plus large. processus et le code appelant fera d’autres manipulations. Dans ce cas, je pourrais peut-être envisager de renvoyer un StringBuilder .

Puisque vous n'allez plus le modifier

return sb.ToString();

devrait être le plus efficace

Renvoyez le sb.ToString (). Votre méthode devrait se concentrer uniquement sur la chose en main (dans ce cas, construisez-moi une chaîne) et ne pas être renvoyée pour être manipulée plus tard, vous pourriez avoir toutes sortes de problèmes avec le fait de ne pas en disposer.

Cela dépend de ce que vous comptez faire avec la sortie. Je retournerais une chaîne personnellement. De cette façon, si vous devez modifier la méthode pour ne pas utiliser de constructeur de chaînes, vous pouvez ne pas être pris comme valeur de retour.

En y réfléchissant pour le moment, la réponse est beaucoup plus claire. La question de savoir lequel doit être retourné répond vraiment à la question. L'objet de retour doit être une chaîne. La raison en est que si vous posez la question, "Y a-t-il une raison pour renvoyer l'objet StringBuilder lorsqu'une chaîne fera l'affaire?" alors la réponse est non. S'il y avait une raison, renvoyer une chaîne serait hors de question, car les méthodes et les propriétés du constructeur de chaînes sont nécessaires.

Si vous devez ajouter d'autres éléments à la chaîne et utiliser d'autres fonctionnalités liées au constructeur de chaînes, renvoyez le constructeur de chaînes. Sinon, si vous utilisez simplement la chaîne elle-même, retournez-la.

Il existe d’autres considérations plus techniques, mais c’est la plus grande préoccupation.

La méthode a été affectée à une tâche concrète et il faut s’attendre à ce qu’elle s’achève et renvoie le résultat final qui ne nécessite aucun traitement supplémentaire. Ne renvoyez StringBuilder que lorsque vous en avez vraiment besoin. Dans ce cas, ajoutez également quelque chose au nom de la méthode pour indiquer que vous retournez quelque chose de spécial.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top