Domanda

I problemi sono:

  • Le librerie della GUI amano usare ToString come rappresentazione predefinita per le classi. Lì deve essere localizzato.
  • ToString viene utilizzato per la registrazione. Lì dovrebbe fornire informazioni relative alla programmazione, non è tradotto e include stati interni come chiavi surrogate e valori enum.
  • ToString viene utilizzato da molte operazioni sulle stringhe che accettano oggetti come argomenti, ad esempio String.Format , quando si scrive su flussi. A seconda del contesto, ti aspetti qualcosa di diverso.
  • ToString è troppo limitato se ci sono molte rappresentazioni diverse dello stesso oggetto, ad es. una forma lunga e una breve.

A causa dei diversi usi, ci sono molti diversi tipi di implementazione. Quindi sono troppo inaffidabili per essere davvero utili.

Come dovrebbe essere implementato ToString per essere utile? Quando deve essere usato ToString , quando dovrebbe essere evitato?


La Documentazione .NET Framework dice:

  

Questo metodo restituisce un valore leggibile   stringa sensibile alla cultura.

Esiste una domanda simile , ma non uguale.

È stato utile?

Soluzione

Sembra che tu abbia grandi aspettative da un piccolo metodo :) Per quanto ne so non è una buona idea usare un metodo generale in così tanti contesti diversi specialmente quando il suo comportamento può differire da classe a classe.

Ecco i miei suggerimenti:

1.Non lasciare che le librerie della GUI utilizzino ToString () dei tuoi oggetti. Usa invece proprietà più significative (quasi tutti i controlli possono essere personalizzati per mostrare altre proprietà oltre a ToString) ad esempio utilizzare DisplayMember. 2.Quando si ottengono alcune informazioni su un oggetto (per la registrazione o altri usi), lasciare che qualcuno decida (un altro oggetto o l'oggetto stesso) cosa dovrebbe essere fornito e come dovrebbe essere visualizzato (un modello di strategia può tornare utile)

Altri suggerimenti

Dipende dall'uso indotto della tua classe. Molte classi non hanno una rappresentazione in stringa naturale (cioè un oggetto Form). Quindi implementerei ToString come metodo informativo (testo del modulo, dimensioni e così via) utile durante il debug. Se la classe intende fornire informazioni all'utente, implementerei ToString come rappresentazione predefinita del valore. Se ad esempio hai un oggetto Vector, ToString potrebbe restituire il vettore come coordinata X e Y. Qui aggiungerei anche metodi alternativi se ci sono altri modi per descrivere la classe. Quindi per il Vector potrei aggiungere un metodo che restituisce una descrizione come un angolo e una lunghezza.

Ai fini del debug potresti anche aggiungere l'attributo DebuggerDisplay alla tua classe. Questo spiega come visualizzare la classe nel debugger, ma non influisce sulla rappresentazione della stringa.

Puoi anche considerare di rendere analizzabile il valore restituito da ToString in modo da poter creare un oggetto da una rappresentazione di stringa. Come puoi fare con il metodo Int32.Parse.

Un'altra ruga da considerare è la stretta integrazione tra ToString e il debugger di Visual Studio. La finestra di controllo visualizza il risultato di ToString come valore dell'espressione, quindi se il tuo metodo esegue un caricamento lento, ha effetti collaterali o impiega molto tempo, potresti vedere comportamenti strani o il debugger potrebbe bloccarsi . Certo, queste qualità non sono il segno distintivo di un metodo ToString ben progettato, ma si verificano (ad esempio un ingenuo "recuperare la traduzione dal database").

Di conseguenza, considero il metodo ToString predefinito (senza parametri) come un hook di debug di Visual Studio - con la conseguenza che non dovrebbe essere generalmente sovraccaricato per l'uso da parte del programma al di fuori di un contesto di debug.

Mentre coloro che conoscono sfruttano gli attributi di debug (DebuggerTypeProxyAttribute, DebuggerDisplayAttribute, DebuggerBrowsableAttribute) per personalizzare il debugger, molti (incluso me stesso) generalmente considerano l'output predefinito generato da ToString e visualizzato nelle finestre di Watch come abbastanza buono.

Comprendo che questa è una prospettiva piuttosto rigorosa - scrivere ToString come hook di debugger - ma trovo che l'implementazione di IFormattable sembra essere la via più affidabile ed estensibile.

Personalmente, non implemento ToString così spesso. In molti casi, non avrebbe molto senso, dal momento che il ruolo principale di un tipo potrebbe è definire il comportamento, non i dati. In altri casi, semplicemente non importa perché nessun cliente ne ha mai bisogno.

In ogni caso, ecco alcuni casi in cui ha senso (non un elenco esaustivo):

  • Se il risultato di ToString potesse essere concepito, può essere analizzato nuovamente in un'istanza del tipo senza perdita di dati.
  • Quando il tipo ha un valore semplice (cioè non complesso).
  • Quando lo scopo principale del tipo è formattare i dati in testo.

Non sono d'accordo che ci sia un conflitto tra gli scenari di utilizzo che elenchi. Quando display è lo scopo principale, ToString dovrebbe fornire un testo intuitivo, ma per la registrazione (o meglio, come lo descrivi, per la traccia), direi che non dovresti tracciare un elemento specifico dell'interfaccia utente in ogni caso, ma piuttosto un oggetto il cui scopo è scrivere dati di traccia dettagliati.

Quindi non vi è alcun conflitto perché non dovrebbe essere dello stesso tipo secondo il principio di responsabilità singola.

Ricorda che puoi sempre sovraccaricare il metodo ToString se hai bisogno di più controllo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top