Laden...

Konvertierung in beliebigen Typ

Erstellt von andski vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.550 Views
A
andski Themenstarter:in
9 Beiträge seit 2013
vor 10 Jahren
Konvertierung in beliebigen Typ

Hallo,

ich habe ein kleines Projekt in welchem ich in einer Hashtable Werte ablege. Diese Werte werden aus einer textbasierten ini-Datei ausgelesen und können vom Typ int, double oder string sein. An anderen Stellen im Programm wird dann mit diesen Werten gearbeitet. An diesen Stellen möchte ich keine Typkonvertierung machen müssen. Mein bisheriges Vorgehen sieht irgendwie so aus:


public object convertTo(string toConvert)
{
    double dVal;
    if (double.TryParse(toConvert, out dVal))
        return dVal;

    return toConvert;
}

Letztlich bekomme ich an den Stellen, an denen ich mit den bereits konvertierten Werten arbeiten will also ein object mit richtigem Typ. Nun ist nur noch ein Cast notwendig:


double d = (double)convertTo("1.0");

Meine Frage: Gibt es eine bessere Möglichkeit, Werte aus einer ini-Datei in die vermeintlichen Typen zu konvertieren? Vielleicht so, dass der Cast zum schluss auch noch wegfällt?

Gruß und Dank

D
41 Beiträge seit 2010
vor 10 Jahren

Vielleicht was in der Richtung?

public T GetValueAs<T>(string key)
{
    if(!_table.ContainsKey(key))
        throw new ArgumentException("key");

    return (T)Convert.ChangeType(_table[key], typeof(T));
    //return (T)Convert.ChangeType(_table[key], typeof(T), new CultureInfo("en-US"));
}

_table ist dein Dictionary...

var _int = GetValueAs<int>("test1");
var _string = GetValueAs<string>("test2");
var _double = GetValueAs<double>("test3");

Beim umwandeln in Kommazahlen kann es sein, dass du deine Spracheinstellungen (CultureInfo) anpassen musst, da in Deutschland als Dezimaltrennzeichen "," - meist jedoch "." verwendet wird. Dazu kannst du an ChangeType als drittes Argument eine CultureInfo Instanz übergeben.

Fehlerbehebung für nicht konvertierbare Werte solltest du auch nicht vergessen...

A
andski Themenstarter:in
9 Beiträge seit 2013
vor 10 Jahren

Hallo und danke für die Antwort.
Deine Variante hat, wie mir auffiel, vor allem einen Vorteil:
Steckt man (T)Convert.ChangeType(...) in einen try-catch-Block, kann man bei erfolgloser Konvertierung zumindest den default-Wert des Typs T zurückgeben. Somit ist im weiteren Programmablauf sichergestellt, dass auch wirklich der entsprechende erwartete Typ vorliegt.

Bei meiner Variante wird bei missglückter Konvertierung der String so zurückgegeben, wie er der Methode übergeben wurde. Bei der Verwendung eines erwarteten double Wertes würde der entsprechende Cast fehlschlagen. Sowas müsste dann ständig abgefangen werden.

Die Methode sieht nun so aus:


public T GetValueAs<T>(string key)
{
    T ret;
    try
    {
        ret = (T)Convert.ChangeType(key, typeof(T), CultureInfo.InvariantCulture);
    }
    catch (Exception e)
    {
        ret = default(T);
    }
    return ret;
}

5.941 Beiträge seit 2005
vor 10 Jahren

Hallo andski

Nicht nur in deinem Fall, sondern auch im Web ist so eine Methode nützlich. Denn da kommt auch vieles als String daher.
Bei meiner Lösung hast du noch die Möglichkeit, optional einen Standardwert anzugeben, falls es fehlschlägt und es wird auch Nullable<T> unterstützt.

Ansonsten sieht es sehr ähnlich aus.

Der Code:


public static partial class Common
{
    /// <summary>
    /// Gibt ein typisiertes Objekt aus einem String zurück.
    /// Falls die Umwandlung nicht erfolgreich ist, wird stattdessen
    /// der Standardwert des Zieltypen zurückgegeben.
    /// </summary>
    /// <typeparam name="T">Zieltyp</typeparam>
    /// <param name="value">Zu typisierenden String</param>
    /// <param name="defaultValue">Standardwert (Wird bei Fehlschlag zurückgegeben)</param>
    /// <returns>Typisiertes Objekt</returns>
    public static T ToOrDefault<T>(this string value, T defaultValue)
    {
      T result = defaultValue;

      if (value == null)
        return result;

      TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
      if (converter.CanConvertFrom(typeof(string)))
      {
        try
        {
          result = (T)converter.ConvertFrom(value);
        } catch (Exception) {}
      }

      return result;
    }

    /// <summary>
    /// Gibt ein typisiertes Objekt aus einem String zurück.
    /// Falls die Umwandlung nicht erfolgreich ist, wird stattdessen
    /// der Standardwert des Zieltypen zurückgegeben.
    /// </summary>
    /// <typeparam name="T">Zieltyp</typeparam>
    /// <param name="value">Zu typisierenden String</param>
    /// <returns>Typisiertes Objekt</returns>
    public static T ToOrDefault<T>(this string value) {
        return value.ToOrDefault<T>(default(T));
    }
}

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

2.921 Beiträge seit 2005
vor 10 Jahren

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.