2010-02-16 2 views
5

Quello che sto facendo è cercare un valore per un campo particolare nella tabella hash. L'oggetto può essere una manciata di tipi primitivi il cui valore è destinato a essere inserito in XML ma esce dalla tabella hash come oggetto. Quindi ho il problema di dover decidere quale sia il tipo, lanciarlo e quindi usare quel tipo di ToString. Sarebbe bello se non avessi bisogno di lanciarlo, ma poi chiamerà ToString sul tipo di oggetto e non sul metodo di contropartita sul tipo effettivo.Un modo pulito per trasmettere a un oggetto il tipo effettivo

Il seguente codice è funzionalmente corretto, ma non mi sento a mio agio. Forse seguire questa via di conforto mi porterà ad essere un purista. Ad ogni modo apprezzerei molto un modo più bello di scrivere questo se esiste.

public string GetColumnValue(string columnName) 
     { 
      object value = item[columnName]; 

      if (value == null) 
       return string.Empty; 

      if (value.GetType() == typeof(string)) 
      { 
       return (string)value; 
      } 
      else if (value.GetType() == typeof(double)) 
      { 
       return ((double)value).ToString(); 
      } 
      ... 
     } 

risposta

8

Se tutti si sta facendo sta chiamando ToString, a causa della natura polimorfica di C#, il ToString chiamerà la corretta applicazione, anche se tutto quello che hai è un riferimento all'oggetto.

Es .:

var d=DateTime.Now; 
object od=d; 
Console.WriteLine(od.ToString()); 
Console.WriteLine(d.ToString()); //same as previous line 
+1

Questo funziona per i tipi di base, ma potrebbe non funzionare bene per i tipi personalizzati - dipende da cosa può essere restituito nella voce [columnName] ... –

+0

Reed, puoi fare un esempio? – spender

+0

Onestamente non pensavo che avrebbe funzionato. Quindi, per amor di discussione, come si può chiamare esplicitamente un'implementazione ToString su un particolare tipo di un albero ereditario? –

1

seconda della lista dei tipi accettabili, si può prendere in considerazione l'utilizzo Convert.ToString e/o la IConvertable interface.

Ciò consentirà di gestire la maggior parte dei tipi primitivi in ​​un'unica operazione.

Sarà comunque necessario gestire il controllo null, tuttavia.

0

Perché non è possibile utilizzare .ToString() su value poiché .ToString() è ereditato dall'oggetto? Verrà chiamato .ToString() per il tipo appropriato più avanti nella catena di ereditarietà.

+0

Tuttavia, è necessario il controllo nullo. –

1

modificare

codici di prova sono qui, se qualcuno è interessato: http://gist.github.com/raw/305787/dc5349d9f6fa37ee5d621b43ec92dade60fe1c8d/ToStringTests.cs

Di seguito troverete la mia risposta originale. Qualcuno ha sottolineato che potresti avere un tipo che non ha un ToString() che ti piace (perché usa Object o qualcosa di più in alto nella catena). Il modo migliore per gestire questa situazione in 3.0+ è con un metodo di estensione come questo:

public static class ToStringExpander 
    { 
     public static string MyToString (this Object x) 
     { 
      return x.ToString(); 
     } 

     public static string MyToString (this mytype x) 
     { 
      return "This is the to string of mytype!"; 
     } 
    } 

Ora mytype lavorerà con il GetColumnValue di seguito se si cambia ToString() per MyToString()

post originale

Questo farà quello che vuoi.

public string GetColumnValue(string columnName) 
    { 
     object value = item[columnName]; 

     if (value == null) 
      return string.Empty; 

     return object.ToString(); 
    } 

o se si vuole guardare vecchia scuola:

public string GetColumnValue(string columnName) 
    { 
     return (item[columnName] == null ? string.Empty : item[columnName].ToString()); 
    } 

certamente vero vecchia scuola sarebbe quello di fare una macro #define ...

+1

Le regole di risoluzione dei nomi metodo richiedono che i metodi dei membri di un oggetto siano selezionati preferibilmente a qualsiasi metodo di estensione che potrebbe essere incluso nell'ambito. Quindi sono abbastanza sicuro che ciò che stai suggerendo qui non funzionerà. –

+0

Sì, l'ho appena testato, il libro che stavo leggendo implicava che avrebbe agito come descritto, ho cambiato la risposta a una nuova soluzione. – Hogan

0

ToString() è un metodo virtuale. Ciò significa che qualsiasi chiamata a quel metodo, in fase di runtime, selezionerà l'implementazione corretta (il "tipo più derivato"). Dal momento che tutti i tipi primitivi hanno la precedenza su ToString() per fare la cosa giusta, non c'è alcun motivo per lanciare su qualsiasi tipo di variabile.

Per un metodo virtuale, il tipo di variabile non ha importanza nella selezione dell'implementazione corretta. Tutto ciò che conta è il tipo di runtime dell'oggetto a cui viene fatto riferimento.

int x = 10; 
object o = x; 
x.ToString(); 
o.ToString(); 

Entrambe le chiamate verso ToString() si eseguono lo stesso codice (meno l'unboxing che si verifica nella versione object, poiché int è un tipo di valore).