Pourquoi / quand serait-il approprié de remplacer ToString?

j'étudie C# et je me demande Quel est l'intérêt et l'avantage de remplacer ToString , comme le montre l'exemple ci-dessous.

est-ce que cela pourrait être fait d'une manière plus simple, en utilisant une méthode commune sans le contrôleur?

public string GetToStringItemsHeadings
{
    get { return string.Format("{0,-20} {1, -20}", "Office Email", "Private Email"); }
}


public override string ToString()
{
    string strOut = string.Format("{0,-20} {1, -20}", m_work, m_personal);
    return strOut;
}
98
demandé sur John Ferguson 2012-04-23 13:36:25

16 réponses

  • avez-vous besoin de remplacer ToString ? Pas de.

  • pouvez-vous obtenir une représentation en chaîne de votre objet d'une autre manière? Oui.

mais en utilisant ToString vous utilisez une méthode qui est commune à tous les objets et donc d'autres classes connaissent cette méthode. Par exemple, lors de la .net framework veut convertir un objet en une représentation string, ToString est un candidat principal (il y en a d'autres, si vous voulez fournir des options de formatage plus élaborées).

concrètement,

Console.WriteLine(yourObject);

invoquerait yourObject.ToString() .

125
répondu Konrad Rudolph 2012-04-23 09:40:11

je vais vous donner la réponse directement à partir des Framework Design Guidelines de la série de développement .NET.

éviter lancer des exceptions de ToString

prendre en considération retour d'une unique chaîne de caractères associée à l'instance.

prendre en considération avoir la sortie de ToString être valide entrée pour toute méthode d'analyse sur ce type.

DO s'assurer que ToString n'a aucun effet secondaire observable.

FAIRE rapport à la sécurité des informations sensibles par le biais d'une substitution de ToString seulement après avoir demandé une autorisation appropriée. Si la demande de permission échoue, retournez une chaîne de caractères excluant les informations sensibles sur le plan de la sécurité.

la méthode Object.ToString est destiné à être utilisé à des fins générales d'affichage et de débogage. L'implémentation par défaut fournit simplement le type d'objet nom. L'implémentation par défaut n'est pas très utile, et il est recommandé que la méthode soit remplacée.

FAIRE remplacer ToString chaque fois que l'un d'intéressant, lisible par l'homme de chaîne peuvent être retournés. L'implémentation par défaut n'est pas très utile, et une implémentation personnalisée peut presque toujours fournir plus de valeur.

FAIRE préférez un nom convivial de plus de un unique, mais pas lisible ID.

il est également intéressant de mentionner que Chris Sells explique également dans les lignes directrices que ToString est souvent dangereux pour les interfaces utilisateur. En général, ma règle de base est d'exposer une propriété qui serait utilisée pour lier des informations à L'UI, et de laisser le ToString outrepasser pour afficher des informations de diagnostic au développeur. Vous pouvez également décorez votre type avec DebuggerDisplayAttribute ainsi.

FAIRE essayez de garder la chaîne renvoyée par ToString court. Le débogueur utilise ToString pour obtenir une représentation textuelle d'un objet à montrer au développeur. Si la chaîne est plus longue que le débogueur peut afficher, l'expérience de débogage est entravée.

DO formatage de chaîne basé sur la culture de fil courant lors du retour information dépendante de la culture.

FAIRE fournir "surcharge 1519110920" , ou de mettre en œuvre IFormattable , si la chaîne de retour de ToString est sensible à la culture, ou il existe différentes façons de mettre en forme la chaîne. Par exemple, DateTime fournit la surcharge et met en œuvre IFormattable .

NE PAS renvoie une chaîne vide ou null à partir de ToString

je jure par ces lignes directrices, et vous devriez. Je ne peux pas vous dire comment mon code a été amélioré par cette seule ligne directrice pour ToString . La même chose vaut pour des choses comme IEquatable(Of T) et IComparable(Of T) . Ces choses rendent votre code très fonctionnel, et vous ne regretterez pas de prendre le temps supplémentaire pour mettre en œuvre tout cela.

personnellement, je n'ai jamais vraiment utilisé ToString beaucoup pour les interfaces utilisateur, j'ai toujours exposé une propriété ou une méthode d'un certain type. La plupart du temps, vous devez utiliser ToString pour le débogage et le développement. Utilisez-le pour afficher des informations de diagnostic importantes.

125
répondu David Anderson 2012-04-26 19:43:43

Overriding ToString() vous permet de donner une représentation utile de chaîne de caractères lisible par l'homme d'une classe.

cela signifie que la sortie peut révéler des informations utiles sur votre classe. Par exemple, si vous aviez une classe Personne, vous pourriez choisir d'avoir la sortie ToString() de l'id de la personne, son prénom, son nom de famille, etc. Ceci est extrêmement utile lors du débogage ou de la journalisation.

quant à votre exemple -, il est difficile de dire si votre override est utile sans savoir ce qu'est cette classe - mais l'implémentation elle-même est correcte.

39
répondu Rob Levine 2012-04-23 12:24:18

c'est toujours approprié, mais examinez attentivement les intentions derrière ce que vous affichez

une meilleure question serait de demander:

pourquoi ToString()?

ToString() est la fenêtre dans l'état d'un objet. L'emphase sur indique comme une exigence. Fortement les langages OOP comme Java / C# abusent le modèle OOP en encapsulant le tout dans une classe. Imaginez que vous codez dans une langue qui ne suit pas le modèle fort OOP; considérez si vous utiliseriez une classe ou une fonction. Si vous l'utilisez comme une fonction (i.e. verbe, action) et que l'état interne n'est maintenu que temporairement entre l'entrée et la sortie, ToString () n'ajoutera pas de valeur.

comme d'autres l'ont mentionné, il est important de considérer ce que vous produisez avec ToString () parce qu'il pourrait être utilisé par le débogueur ou d'autres système.

j'aime à imaginer la méthode ToString comme le paramètre --help d'un objet. Il doit être court, lisible, évidente et facile à afficher. Il doit afficher ce que l'objet est et non ce que fait . Avec tout cela à l'esprit, nous allons examiner...

"151940920 Cas d'Utilisation" - de l'Analyse d'un paquet TCP:

pas seulement une capture de réseau au niveau de l'application, mais quelque chose avec plus de viande comme une capture pcap.

vous voulez surcharger ToString() juste pour la couche TCP afin de pouvoir imprimer des données sur la console. Que serait-il? Vous pourriez devenir fou et analyser tous les détails de TCP (c.-à-d. TCP est complexe)...

qui comprend le:

  • Port Source
  • Port De Destination
  • Numéro De Séquence
  • numéro D'accusé de réception
  • offset des Données
  • Drapeaux
  • Offset Fenêtre
  • somme de contrôle
  • Pointeur Urgent
  • Options (Je ne suis pas même va y aller)

mais voudriez-vous recevoir toute cette Camelote si vous appeliez TCP.ToString () Sur 100 paquets? Bien sûr que non, ce serait une surcharge d'information. La facilité et l'évidence le choix est aussi le plus sensé...

exposer ce que les gens s'attendraient à voir:

  • Port Source
  • Port De Destination

je préfère une sortie sensible qui est facile à analyser pour les humains mais YMMV .

TCP:[destination:000, source:000]

rien de Complexe, la sortie n'est pas pour les machines à analyser (c'est-à-dire à moins que les gens abusent de votre code), le but visé est la lisibilité humaine.

mais qu'en est-il du reste de cette information juteuse dont j'ai parlé avant, n'est-ce pas utile aussi? J'y reviendrai mais d'abord...


ToString () l'une des méthodes les plus précieuses et sous-utilisées de tous les temps

pour deux raisons:

  1. les gens ne comprennent pas ce que ToString() est pour
  2. la classe de base 'Object' manque une autre méthode de chaîne, tout aussi importante.

raison 1-Ne pas abuser de L'utilité de ToString ():

beaucoup de gens utilisent ToString() pour tirer une simple représentation string d'un objet. Le manuel C# dit même:

ToString est la principale méthode de formatage dans le .net Framework. Il convertit un objet en son représentation sous forme de chaîne de sorte qu'il est adapté pour l'affichage.

Affichage", 151950920" de ne pas poursuivre le traitement. Cela ne veut pas dire, prendre ma représentation de chaîne de caractères du paquet TCP ci-dessus et tirer le port source en utilisant un regex ::cringe::.

Le droit façon de faire les choses est, appel à ToString() directement sur le SourcePort propriété (qui d'AILLEUR est un ushort donc ToString() devrait déjà être disponible).

si vous avez besoin de quelque chose de plus robuste pour empaqueter l'état d'un objet complexe pour l'analyse automatique, vous serez mieux à l'aide d'une stratégie de sérialisation structurée.

heureusement, de telles stratégies sont très courantes:

  • Iserialisable (C#)
  • Cornichon (Python)
  • JSON (Javascript ou dans la langue qui l'implémente)
  • savon
  • etc...

Note: sauf si vous utilisez PHP parce que, herp-derp, il y a une fonction pour cela:: snicker::

Raison 2 - ToString() n'est pas suffisant:

Je n'ai pas encore vu de langage qui implémente ceci au cœur, mais j'ai vu et utilisé des variantes de cette approche dans la nature.

dont:

  • ToVerboseString ()
  • ToString (verbose=true)

fondamentalement, ce désordre poilu de L'état d'un paquet TCP devrait être décrit pour la lisibilité humaine. Pour éviter de "battre un cheval mort" en parlant de TCP, je vais "pointer du doigt" le cas n ° 1 où je pense que ToString() et ToVerboseString() sont sous-utilisés...

Utiliser Des Cas-Matrices:

si vous utilisez principalement une langue, vous êtes probablement à l'aise avec l'approche de cette langue. Pour des gens comme moi qui passent d'une langue à l'autre, le nombre d'approches variées peut être irritant.

Ie, le nombre de fois que cela m'a irrité est plus grand que la somme de tous les doigts de chaque dieu hindou combiné.

Il y a divers les cas où l'utilisation des langues commun hacks et un peu que obtenir il droit . Certains nécessitent de réinventer la roue, d'autres font une décharge superficielle, d'autres une décharge profonde, aucun d'eux ne fonctionne comme je le voudrais...

ce que je demande est une approche très simple:

print(array.ToString());

sorties: 'Array[x]' ou ' Array[x] [y]'

Où x est le nombre d'éléments dans la première dimension et y est le nombre d'éléments dans la deuxième dimension ou une valeur qui indique que la deuxième dimension est dentelée (min/max peut-être?).

et:

print(array.ToVerboseString());

Affiche Tout ce qu'elle a écrit en jolis caractères parce que j'apprécie les jolies choses.

avec un peu de chance, cela jette un peu de lumière sur un sujet qui m'a agacé pour longtemps. Au moins j'ai saupoudré un petit appât à trolls pour que les PHPers dévalorisent cette réponse.

12
répondu Evan Plaice 2017-05-23 11:46:34

il est question de bonne pratique autant que n'importe quoi, vraiment.

ToString() est utilisé dans de nombreux endroits pour retourner une représentation string d'un objet, généralement pour la consommation par un humain. Souvent, cette même chaîne peut être utilisée pour réhydrater l'objet (pensez à int ou DateTime par exemple), mais ce n'est pas toujours donné (un arbre par exemple, pourrait avoir une représentation de chaîne utile qui affiche simplement un nombre, mais clairement vous ne pouvez pas utiliser cela pour reconstruire).

en particulier, le débogueur va l'utiliser pour afficher la variable dans les fenêtres de montre, fenêtres immédiates, etc, donc ToString est réellement inestimable pour le débogage.

en général, aussi, un tel type aura souvent un membre explicite qui renvoie aussi une chaîne. Par exemple, une paire Lat / Long pourrait avoir ToDecimalDegrees qui renvoie "-10, 50" par exemple , mais elle pourrait aussi avoir ToDegreesMinutesSeconds , puisque c'est un autre format pour une paire Lat/Long. Ce même type pourrait alors remplacer ToString avec l'un de ceux pour fournir un" défaut "pour des choses comme le débogage, ou même potentiellement pour des choses comme le rendu de pages web (par exemple, la construction @ dans Razor écrit le ToString() résultat d'une expression non-chaîne au flux de sortie).

9
répondu Andras Zoltan 2012-04-23 09:48:23

object.ToString() convertit un objet en sa représentation string. Si vous souhaitez modifier ce qui est retourné lorsqu'un utilisateur appelle ToString() sur une classe que vous avez créé, vous devez remplacer ToString() dans cette classe.

6
répondu Robbie 2012-04-23 20:42:17

si vous n'outrepassez pas ToString alors vous obtenez l'implémentation de vos classes de base qui, pour Object est juste le nom de type court de la classe.

si vous voulez une autre mise en œuvre, plus significative ou utile de ToString alors le remplacer.


cela peut être utile lorsque vous utilisez une liste de votre type comme source de données pour un ListBox comme le ToString sera automatiquement affiché.

une autre situation se produit quand vous voulez passer votre type à String.Format qui invoque ToString pour obtenir une représentation de votre type.

5
répondu Jodrell 2012-04-23 09:56:50

bien que je pense que l'information la plus utile a déjà été fournie, je vais ajouter mes deux cents:

  • ToString() est destiné à être dépassé. Son implémentation par défaut renvoie le nom du type qui, bien que peut-être utile à certains moments (en particulier quand on travaille avec beaucoup d'objets), ne suffit pas dans la grande majorité des cas.

  • rappelez-vous que, pour le débogage, vous pouvez compter sur DebuggerDisplayAttribute . Vous pouvez en lire plus à ce sujet ici .

  • en règle générale, sur POCOs, vous pouvez toujours remplacer ToString() . Les POCOs sont une représentation structurée de données, qui peuvent généralement devenir une chaîne.

  • Conception ToString pour être une représentation textuelle de votre objet. Peut-être ses principaux champs et données, peut-être une description du nombre d'éléments de la collection, etc.

  • toujours essayer d'ajuster cette chaîne dans une seule ligne et n'avoir que des informations essentielles. Si vous avez une classe Person avec nom, adresse, numéro, etc. propriétés, retourner Seulement les données principales (nommer un numéro D'identification).

  • veillez à ne pas outrepasser une bonne mise en œuvre de ToString() . Certaines classes framework implémentent déjà ToString() . Passer outre que la mise en œuvre par défaut est une mauvaise chose: attendez-vous à un certain résultat de ToString() et obtenez un autre.

N'ayez pas vraiment peur d'utiliser ToString() . La seule chose que je ferais attention, c'est de rendre des informations sensibles. Autre que cela, le risque est minime. Bien sûr, comme certains l'ont souligné, d'autres classes utiliseront votre ToString chaque fois qu'ils chercheront des informations. Mais bon sang, quand est-ce que retourner le nom de type sera considéré comme mieux que d'obtenir quelques informations réelles?

5
répondu Bruno Brant 2012-04-25 22:13:04

quelque chose que personne d'autre n'a encore mentionné: en remplaçant ToString() , vous pouvez également envisager de remplacer ToString(string Formatter) de sorte que vous pouvez faire ce qui suit:

 public override ToString() {
   string strOut = string.Format("{0,-20} {1, -20}", m_work, m_personal);
   return strOut;
 }

 public override ToString(string formatter) {
   string strOut = this.ToString();
   switch (formatter.ToLower()) {
     case "w":
       strOut = m_Work;
       break;
     case "p":
       strOut = m_Personal;
       break;
     case "hw":
       strOut = string.Format("mailto:{0}", m_Work);
       break;
   }
   return strOut;
}

qui peut être utile.

4
répondu Zhaph - Ben Duguid 2012-05-04 22:24:49

un avantage de ToString() est le support d'outils de Resharper: Alt + Ins - > " formater les membres " et il écrit le ToString() pour vous.

3
répondu Daniel James Bryars 2012-04-24 21:54:16

dans certains cas, il est plus facile de lire les valeurs des classes personnalisées dans la fenêtre de surveillance du débogueur. Si je sais exactement ce que je veux voir dans la fenêtre de la montre, quand je remplace ToString avec cette information, Alors je le vois.

2
répondu philologon 2012-04-23 15:59:06

lors de la définition de structures (effectivement utilisateurs-primitives) je trouve qu'il est de bonne pratique d'avoir des méthodes de correspondance ToString , et Parse et TryParse , en particulier pour la sérialisation XML. Dans ce cas, vous convertirez l'état entier en chaîne, de sorte qu'il puisse être lu plus tard.

Les classes

sont toutefois des structures plus composées qui seront généralement trop complexes pour pouvoir utiliser ToString et Parse . Leurs méthodes ToString , au lieu de sauvegarder l'état entier, peut être une simple description qui vous aide à identifier leur état, comme un identifiant unique comme un nom ou un ID, ou peut-être une quantité pour une liste.

aussi, comme L'a dit Robbie, la suppression de ToString vous permet d'appeler ToString sur une référence aussi basique que le type object .

1
répondu Dave Cousineau 2012-04-23 17:58:48

vous pouvez utiliser cela quand vous avez un objet avec un sens non intuitif de la représentation de chaîne, comme personne. Donc, si vous avez besoin par exemple d'imprimer cette personne, vous pouvez utiliser cette commande pour préparer son format.

1
répondu NickF 2012-04-25 07:19:42

la méthode Object.ToString ne doit être utilisée qu'à des fins de débogage. L'implémentation par défaut montre le nom du type d'objet qui n'est pas très utile. Envisager de remplacer cette méthode pour fournir de meilleures informations pour le diagnostic et de débogage. S'il vous plaît considérer que les infrastructures de journalisation utilisent souvent la méthode ToString aussi bien et donc vous trouverez ces fragments de texte dans vos fichiers de log.

Ne pas retour texte localisé ressources dans la méthode Object.ToString . La raison en est que la méthode ToString doit toujours retourner quelque chose que le développeur peut comprendre. Le développeur peut ne pas parler toutes les langues que l'application supporte.

implémenter l'interface IFormattable lorsque vous voulez retourner un texte localisé convivial. Cette interface définit une surcharge ToString avec les paramètres format et formatProvider . Le formatProvider vous aide à formater le texte d'une manière consciente de la culture.

Voir Aussi: objet.ToString et IFormattable

1
répondu jbe 2015-10-03 08:50:48

Simple dépend de la façon dont votre propriété va être utilisé. Si vous avez juste besoin de formater la chaîne d'un temps, puis il ne fait pas beaucoup de sens, primordial.

Cependant, Il semble que vous substituez la méthode ToString pour pas de retour à la normale de la chaîne de données pour votre propriété , mais pour effectuer une mise en forme standard modèle. Puisque vous utilisez string.format avec rembourrage.

parce que vous dites que vous apprenez, l'exercice apparaît aussi frapper sur les principes fondamentaux de la programmation orientée objet se rapportant à l'encapsulation de code et de le ré-utiliser.

la corde.format prenant les arguments que vous avez mis pour le padding assure que la propriété sera formatée de la même manière à chaque fois pour n'importe quel code qui l'appelle. Ainsi, à l'avenir, vous n'avez qu'à modifier dans un seul endroit au lieu de plusieurs.

grande question et aussi quelques grandes réponses!

0
répondu SoftwareCarpenter 2012-04-25 15:05:14

je trouve utile de surcharger la méthode ToString sur les classes entity car elle permet d'identifier rapidement les problèmes dans testing en particulier quand une assertion échoue la console de test va invoquer la méthode ToString sur l'objet.

mais en accord avec ce qui a été dit avant c'est de donner une représentation humaine lisible de l'objet en question.

0
répondu ranjez 2012-04-27 10:05:27