2010-02-16 17 views
5

Co robię, to szukam wartości dla określonego pola w tablicy hashtable. Obiekt może być garstką prymitywnych typów, których wartość ma być umieszczona wewnątrz XML, ale wychodzi z tablicy jako obiektu. Tak więc mam problem z koniecznością podjęcia decyzji o typie, rzucić go, a następnie użyć tego typu ToString. Byłoby miło, gdybym nie musiał go rzucać, ale wtedy wywoła to ToString na typie obiektu, a nie na metodę odpowiednika w rzeczywistym typie.Czysty sposób rzutowania na rzeczywisty typ obiektu

Poniższy kod jest funkcjonalnie poprawny, ale nie jestem z nim zadowolony. Być może podążanie tą ścieżką pocieszenia doprowadzi mnie do bycia purystą. Tak czy inaczej bardzo doceniam lepszy sposób napisania tego, jeśli taki istnieje.

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(); 
      } 
      ... 
     } 

Odpowiedz

8

Jeśli wszystko robisz dzwoni ToString, ze względu na charakter polimorficzny C# ToString zwróci prawidłowej realizacji, nawet jeśli wszystko masz to odniesienie do obiektu.

Np .:

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

Działa to dla podstawowych typów, ale może nie działać dobrze dla typów niestandardowych - zależy od tego, co można zwrócić w pozycji [columnName] ... –

+0

Reed, czy możesz podać przykład? – spender

+0

Szczerze mówiąc, nie sądziłem, że to zadziała. Tak więc dla argumentów, w jaki sposób można jawnie wywołać implementację ToString dla określonego typu drzewa dziedziczenia? –

1

zależności od listy dopuszczalnych typów, można rozważyć użycie Convert.ToString i/lub IConvertable interface.

Pozwoli to obsłużyć większość typów pierwotnych za jednym razem.

Nadal musisz jednak wykonać kontrolę zerową.

0

Dlaczego nie można po prostu użyć .ToString() na value od .ToString() jest dziedziczone z obiektu? Zostanie wywołana metoda .ToString() dla odpowiedniego typu w górę łańcucha dziedziczenia.

+0

Nadal jednak wymaga kontroli zerowej. –

1

edit

kody testowe są tutaj, jeśli ktoś jest zainteresowany: http://gist.github.com/raw/305787/dc5349d9f6fa37ee5d621b43ec92dade60fe1c8d/ToStringTests.cs

Poniżej znajdziecie mój oryginalny odpowiedź. Ktoś wskazał, że możesz mieć typ, który nie ma funkcji ToString(), którą lubisz (ponieważ używa obiektu lub czegoś wyżej w łańcuchu). Najlepszym sposobem, aby sobie z tym poradzić w 3.0 lub nowszą jest o metodę rozszerzenia jak ten:

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!"; 
     } 
    } 

Teraz MyType współpracować z GetColumnValue poniżej jeśli zmienisz toString()() do MyToString

oryginalnego postu

To zrobi, co chcesz.

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

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

     return object.ToString(); 
    } 

lub jeśli chcesz wyglądać starej szkoły:

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

oczywiście prawdziwy old school byłoby zrobić #define makro ...

+1

Reguły rozpoznawania nazw metod wymagają, aby metody elementów obiektu były wybierane przed wszystkimi metodami rozszerzeń, które mogą znajdować się w zakresie. Jestem prawie pewien, że to, co sugerujesz, nie zadziała. –

+0

Tak, właśnie to przetestowałem, książka, którą czytałem sugerowała, że ​​zachowałaby się jak opisałem, zmieniłem odpowiedź na nowe rozwiązanie. – Hogan

0

ToString() jest metoda wirtualna. Oznacza to, że wszelkie wywołania tej metody będą w czasie wykonywania wybierać poprawną implementację ("najbardziej wyprowadzony typ"). Ponieważ wszystkie typy pierwotne zastępują ToString(), aby zrobić właściwą rzecz, nie ma powodu do rzucania jakiejkolwiek zmiennej.

Dla metody wirtualnej typ zmiennej nie ma znaczenia przy wyborze poprawnej implementacji. Liczy się jedynie typ środowiska wykonawczego, do którego się odwołuje.

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

Oba wywołania ToString() wykona ten sam kod (Minus unboxing, który występuje w wersji object, ponieważ int jest typem wartości).

Powiązane problemy