2009-09-10 24 views
7

Los problemas son:C#: ¿Cómo se debe implementar ToString()?

  • bibliotecas GUI les gusta usar ToString como una representación por defecto para las clases. Allí necesita ser localizado.
  • ToString se utiliza para el registro. Allí debe proporcionar información relacionada con la programación, no está traducida e incluye estados internos como claves sustitutas y valores enum.
  • ToString es utilizado por muchas operaciones de cadena que toman objetos como argumentos, por ejemplo String.Format, al escribir en las secuencias. Dependiendo del contexto, esperas algo diferente.
  • ToString es muy limitado si hay muchas representaciones diferentes del mismo objeto, por ej. una forma larga y una corta.

Debido a los diferentes usos, hay muchos tipos diferentes de implementación. Entonces son demasiado poco confiables para ser realmente útiles.

¿Cómo se debe implementar ToString para que sea útil? ¿Cuándo se debe usar ToString? ¿Cuándo se debe evitar?


El .NET Framework documentation dice:

Este método devuelve una legible cadena que es sensible a la cultura.

Hay similar question, pero no es lo mismo.

Respuesta

5

Parece que tiene grandes expectativas de un minúsculo método :) Por lo que yo sé que no es una buena idea utilizar un método general en muchos contextos diferentes, especialmente cuando su comportamiento puede diferir de una clase a otra.

Aquí está mi sugerencia:

1.Do no dejar que las librerías gráficas utilizan ToString() de su objects.Instead utilizar las propiedades más significativas (Casi todos los controles se pueden personalizar para mostrar otras propiedades que ToString) por ejemplo, usa DisplayMember. 2. Al obtener información sobre un objeto (para el registro u otros usos) deje que alguien decida (otro objeto o el objeto mismo) qué se debe proporcionar y cómo se debe mostrar (un patrón de estrategia puede ser útil)

+0

No esperaría tanto si no se llamara implícitamente por todo el lugar. Pero probablemente tengas razón. Debería evitar que se use implícitamente en la interfaz de usuario. –

1

Depende del uso indended de su clase. Muchas clases no tienen una representación de cadena natural (es decir, un objeto Form). Luego implementaría ToString como un método informativo (texto del formulario, tamaño, etc.) útil para la depuración. Si la clase está destinada a dar información al usuario, implementaría ToString como una representación predeterminada del valor. Si tiene un objeto Vector por ejemplo, ToString podría devolver el vector como una coordenada X e Y. Aquí también agregaría métodos alternativos si hay otras formas de describir la clase. Entonces, para el Vector, podría agregar un método que devuelva una descripción como un ángulo y una longitud.

Para la depuración, es posible que también desee agregar el atributo DebuggerDisplay a su clase. Esto le dice cómo mostrar la clase en el depurador, pero no afecta la representación de cadena.

Es posible que también desee considerar hacer que el valor devuelto por ToString sea parseable para que pueda crear un objeto a partir de una representación de cadena. Como puedes hacer con el método Int32.Parse.

0

Personalmente, no implemento ToString con tanta frecuencia. En muchos casos, no tendría mucho sentido, ya que la función principal de un tipo puede ser para definir el comportamiento, no los datos. En otros casos, simplemente no importa porque ningún cliente lo necesita.

En cualquier caso, aquí hay algunos casos donde tiene sentido (no es una lista exhaustiva):

  • Si el resultado de ToString podría concebible ser analizado de nuevo en una instancia del tipo sin pérdida de datos.
  • Cuando el tipo tiene un valor simple (es decir, no complejo).
  • Cuando el propósito principal del tipo es formatear datos en texto.

No estoy de acuerdo con que exista un conflicto entre los escenarios de uso que enumera. Cuando la visualización es el objetivo principal, ToString debe proporcionar un texto fácil de usar, pero para el registro (o más bien, como usted lo describe, para el seguimiento) diría que en ningún caso debería estar rastreando un elemento específico de UI, sino más bien un objeto cuyo propósito es escribir datos de seguimiento detallados.

Por lo tanto, no hay conflicto porque no debe ser del mismo tipo según el principio de responsabilidad única.

Recuerde que siempre puede sobrecargar el método ToString si necesita más control.

+0

El problema con "ningún cliente lo necesita" es que se llama implícitamente a ToString. El conflicto surge cuando el mismo objeto se usa en diferentes situaciones. ¿DateTime es una clase específica de UI? Muchas clases no están diseñadas para usarse solo para la interfaz de usuario o solo internamente. "Siempre se puede sobrecargar el ToString": esa es la pregunta: ¿CÓMO debería implementarse entonces? –

+0

Si usa el mismo objeto en situaciones muy diferentes, creo que está violando el SRP ...No, DateTime no es particularmente una clase específica de UI, pero entra en la categoría de poder realizar un viaje de ida y vuelta de ToString/Parse sin pérdida de datos. –

1

Otra arruga a considerar es la estrecha integración entre ToString y el depurador de Visual Studio. La ventana Inspección muestra el resultado de ToString como el valor de la expresión, por lo que si su método realiza alguna carga diferida, tiene efectos secundarios o tarda mucho tiempo, es posible que observe un comportamiento extraño o que el depurador parezca bloquearse. . Por supuesto, estas cualidades no son la marca de un método ToString bien diseñado, pero suceden (por ejemplo, una implementación ingenua de "buscar la traducción desde la base de datos").

En consecuencia, considero que el método ToString predeterminado (sin parámetros) es un enlace de depuración de Visual Studio, con la consecuencia de que generalmente no debe sobrecargarse para que el programa lo use fuera de un contexto de depuración.

mientras que los del apalancamiento conocer los atributos de depuración (DebuggerTypeProxyAttribute, DebuggerDisplayAttribute, DebuggerBrowsableAttribute) para personalizar el depurador, muchos (incluido yo mismo) consideran generalmente la salida por defecto como la generada por ToString y se muestran en las ventanas del reloj a ser lo suficientemente bueno.

Entiendo que esta es una perspectiva bastante estricta, escribiendo ToString como un enlace de depurador, pero me parece que la implementación de IFormattable parece ser la ruta más confiable y extensible.

Cuestiones relacionadas