2009-08-27 14 views
18

Ho un MyClass di classe, e vorrei sovrascrivere il metodo ToString() di casi di listino:override ToString() della Lista <MyClass>

class MyClass 
{ 
    public string Property1 { get; set; } 
    public int Property2 { get; set; } 
    /* ... */ 
    public override string ToString() 
    { 
     return Property1.ToString() + "-" + Property2.ToString(); 
    } 
} 

mi piacerebbe avere la seguente:

var list = new List<MyClass> 
      { 
       new MyClass { Property1 = "A", Property2 = 1 }, 
       new MyClass { Property1 = "Z", Property2 = 2 }, 
      }; 

Console.WriteLine(list.ToString()); /* prints: A-1,Z-2 */ 

È possibile farlo? Oppure dovrei sottoclasse l'Elenco < MyClass> per sovrascrivere il metodo ToString() nella mia sottoclasse? Posso risolvere questo problema usando i metodi di estensione (cioè, è possibile sovrascrivere un metodo con un metodo di estensione)?

Grazie!

+0

Per informazioni: stavo cercando di fare qualcosa relativo a NHibernate e la mappatura delle collezioni in una stringa serializzata che si adatterebbe a una singola colonna. Tuttavia ho trovato un altro modo per farlo, implementando il mio IUserType, e la mia implementazione costruisce la stringa di cui ho bisogno! Grazie a tutti quelli che hanno risposto comunque! –

risposta

21

Avrete bisogno di sottoclasse per sovrascrivere qualsiasi metodo. Il punto di generici è dire che vuoi lo stesso comportamento indipendentemente dal tipo di T. Se vuoi un comportamento diverso per un tipo specifico di T allora stai infrangendo quel contratto e dovrai scrivere la tua classe:

public class MyTypeList : List<MyClass> 
{ 
    public override string ToString() 
    { 
     return ... 
    } 
} 

a cura di aggiungere:

No, non è possibile eseguire l'override un metodo con la creazione di una proroga, ma si potrebbe creare un nuovo metodo con una firma diversa che è specifico per questo tipo di elenco:

public static string ExtendedToString(this List<MyClass> list) 
{ 
    return .... 
} 

Utilizzato con

Penso ancora che è meglio sottoclassi però ...

+1

Questo è un codice così piccolo per la nuova classe elenco, quindi lo includerei in cima allo stesso file di codice della classe 'MyClass'. Quindi questo non è uno sforzo in più da fare, anche se sembra complicato creare una nuova classe, in realtà non è perché la maggior parte delle funzionalità è ereditata dalla classe 'List' ... – awe

+0

** Informazioni sull'estensione metodo: ** Sono d'accordo che in questo caso si dovrebbe andare con la sottoclasse, perché il metodo 'ToString' è logicamente quello che si desidera, e' Elenco' non ha un'implementazione predefinita molto utile di esso. L'estensione aggiungerà un nuovo metodo e lascerà il metodo 'ToString' altrettanto inutile come lo è sempre stato per la generica classe' List'. – awe

0

Si dovrà creare la propria classe personalizzata che eredita da Collezione e poi scriverli il metodo ToString() di quella classe in particolare.

2

Se il metodo deve essere denominato ToString, è necessario ricavare una classe da List. Si può fare un generico:

static class MyList<T> : List<T> 
{ 
    public override string ToString() 
    { 
     // ... 
    } 
} 

In questo caso, si dovrà utilizzare MyList invece di List in tutta l'applicazione, se si desidera avere la vostra conversione personalizzato.

Tuttavia, se si può scegliere un nome diverso per il metodo, è possibile utilizzare metodi di estensione e ottenere lo stesso effetto, con quasi nessuna modifica al codice:

È possibile utilizzare metodi di estensione per rendere questo più generico :

static class ListExtension 
{ 
    public static void ConvertToString<T>(this IEnumerable<T> items) 
    { 
     // ... 
    } 
} 

si può utilizzare su qualsiasi istanza di IEnumerable<T> proprio come se fosse un metodo ordinario:

List<MyClass> list = new List<MyClass> { ... }; 
Console.WriteLine(list.ConvertToString()); 

int[] array_of_ints = {1,2,3,4,5}; 
Console.WriteLine(array_of_ints.ConvertToString()); 
0

No la sua non p ossible. ToString of TList ti darà la rappresentazione in formato stringa dell'oggetto list.

Le opzioni disponibili sono:

  • Derive da TList e l'override del metodo .ToString() come lei ha ricordato.(in questo esempio non direi che vale la pena farlo)
  • Creare un metodo di supporto che converta una lista TList in una stringa delimitata da virgole, ad es. metodo di estensione (probabilmente migliore suggerimento)
  • Utilizzare un'istruzione foreach nella fase Console.WriteLine.

Spero che questo aiuti!

21

Forse un po 'fuori tema, ma io uso un metodo di estensione ToDelimitedString che funziona per qualsiasi IEnumerable<T>. Si può (opzionalmente) specificare il delimitatore da utilizzare e un delegato per eseguire una conversione stringa personalizzata per ogni elemento:

// if you've already overridden ToString in your MyClass object... 
Console.WriteLine(list.ToDelimitedString()); 
// if you don't have a custom ToString method in your MyClass object... 
Console.WriteLine(list.ToDelimitedString(x => x.Property1 + "-" + x.Property2)); 

// ... 

public static class MyExtensionMethods 
{ 
    public static string ToDelimitedString<T>(this IEnumerable<T> source) 
    { 
     return source.ToDelimitedString(x => x.ToString(), 
      CultureInfo.CurrentCulture.TextInfo.ListSeparator); 
    } 

    public static string ToDelimitedString<T>(
     this IEnumerable<T> source, Func<T, string> converter) 
    { 
     return source.ToDelimitedString(converter, 
      CultureInfo.CurrentCulture.TextInfo.ListSeparator); 
    } 

    public static string ToDelimitedString<T>(
     this IEnumerable<T> source, string separator) 
    { 
     return source.ToDelimitedString(x => x.ToString(), separator); 
    } 

    public static string ToDelimitedString<T>(this IEnumerable<T> source, 
     Func<T, string> converter, string separator) 
    { 
     return string.Join(separator, source.Select(converter).ToArray()); 
    } 
} 
+0

Buon suggerimento in generale: anch'io utilizzo un metodo di estensione di questo tipo. A seconda del contesto esatto della domanda originale, questa potrebbe o potrebbe non essere una risposta valida qui. – peSHIr

+0

Questi sono alcuni metodi di estensione davvero a portata di mano, grazie! Aiutami a caricare all'interno di una funzione utilizzando un IList di tipi di enum anonimi per convertirli in un elenco separato da virgole, appena usato (x => ((breve) Convert.ChangeType (x, TypeCode.Int16)) come parametro del mio convertitore. ancora Luke –

+0

Come per il commento di danrichardson, grazie per l'input questo è abbastanza utile! –

0

A seconda del motivo esatto che avete per voler ignorare List<T>.ToString() per tornare qualcosa di specifico che potrebbe essere a portata di mano per dare un'occhiata alle implementazioni personalizzate TypeConverter.

Se si desidera semplicemente un List<T> di specifici T a mostrarsi in un certo modo come string in luoghi in cui vengono utilizzati TypeConverters, come nel debugger o in string.Format("List: {0}", listVariable) situazioni tipo, questo potrebbe essere sufficiente.

È possibile che il risultato di ToString() venga visualizzato da qualche parte e si desideri modificarlo, senza conoscere l'esistenza di TypeConverter e le posizioni in cui vengono utilizzati. Credo che molti/più/tutti (non sono sicuro quale?) Dei TypeConverters di default in .NET Framework usino semplicemente ToString() quando convertono qualsiasi tipo per il quale sono definiti per un string.

2

In realtà è possibile utilizzare un trucco Unicode per consentire di definire un metodo ToString alternativo direttamente rispetto all'elenco generico.

Se si abilita esadecimale di inserimento dei caratteri in Visual Studio allora si può creare personaggi invisibili tenendo premuto il tasto Alt, quindi premendo il seguente sul tastierino numerico + FFF 9 (ora rilasciare Alt)

Così siamo in grado di creare la seguente funzione con un carattere invisibile posizionato accanto al suo nome ... (Sì, lo so il suo codice VB, ma il concetto sarà ancora lavorare lavoro per C#)

<Extension()> _ 
Public Function ToString(ByVal source As Generic.List(Of Char)) As String 
    Return String.Join(separator:="", values:=source.ToArray) 
End Function 

Ora in visual Studio, quando si accede intellisense contro nella tua lista, sarai in grado di scegliere tra la ToString standard o la tua funzione personalizzata.


Per abilitare esadecimale di immissione dei caratteri in Visual Studio potrebbe essere necessario modificare il Registro di sistema

aperta HKEY_CURRENT_USER \ Control Panel \ Input Method e creare un REG_SZ denominata EnableHexNumpad impostato questo per 1

È sarà inoltre necessario disabilitare le scorciatoie & per i menu File, Modifica, Debug, Dati, In Visual Studio, aprire il menu Strumenti, selezionare Personalizza, quindi aprire la scheda comandi e utilizzare il pulsante di modifica modifica per qualsiasi voce di menu che utilizza uno dei ABCDEF per la sua scorciatoia, rimuovendo il &

Altrimenti finirai per aprire i menu popup, invece di digitare caratteri esadecimali.

+0

questo è disgustoso e la tua risposta dovrebbe essere cancellata per tutta l'eternità .... +1 –

+1

Idk se funziona, ma sembra geniale e mi ha dato un buon ridacchia! +1 –

Problemi correlati