Gibt es eine generische Parse () - Funktion, die eine Zeichenfolge mithilfe von parse in einen beliebigen Typ konvertiert?

88

Ich möchte eine Zeichenfolge in einen generischen Typ wie intoder dateoder longbasierend auf dem generischen Rückgabetyp konvertieren .

Grundsätzlich Parse<T>(String)gibt eine solche Funktion ein Element vom Typ zurück T.

Wenn beispielsweise ein int übergeben wurde, sollte die Funktion int.parseintern ausgeführt werden.

Karim
quelle

Antworten:

128

System.Convert.ChangeType

Nach Ihrem Beispiel könnten Sie Folgendes tun:

int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));

Um Ihre Anforderung "generischer Rückgabetyp" zu erfüllen, können Sie Ihre eigene Erweiterungsmethode schreiben:

public static T ChangeType<T>(this object obj)
{
    return (T)Convert.ChangeType(obj, typeof(T));
}

Auf diese Weise können Sie Folgendes tun:

int i = "123".ChangeType<int>();
Ani
quelle
cool, aber das seltsame Ding heißt ChangeType, also würde ich denken, dass diese Funktion eine Art Cast macht und nicht analysiert
Karim
7
Laut MSDN handelt es sich lediglich um einen Wrapper, der die richtige Konvertierungsmethode für das Quellobjekt findet und die IConvertible-Schnittstelle implementiert.
Ani
Wenn es implementiert IConvertablewerden muss, sollten Sie nicht auch das einschränken T, dh T ChangeType<T>(this object obj) where T : IConvertable?
Liam
2
@Liam: Nein, objdas muss sein IConvertible, aber es gibt keine Möglichkeit, dies zur Kompilierungszeit anzugeben.
Ani
Wenn ich etwas wie TryChangeType benötige, das im Fehlerfall null oder false zurückgibt? Nur durch Ausnahme?
Hoffnungslos
20

Es sieht so aus, als wäre ich zu spät, um auf diesen Thread zu antworten. Aber hier ist meine Implementierung:

Grundsätzlich habe ich eine Erweiterungsmethode für die Object-Klasse erstellt. Es behandelt alle Typen, dh nullable, Klassen und Strukturen.

 public static T ConvertTo<T>(this object value)
           {
               T returnValue;

               if (value is T variable)
                   returnValue = variable;
               else
                   try
                   {
                       //Handling Nullable types i.e, int?, double?, bool? .. etc
                       if (Nullable.GetUnderlyingType(typeof(T)) != null)
                       {
                           TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
                           returnValue = (T) conv.ConvertFrom(value);
                       }
                       else
                       {
                           returnValue = (T) Convert.ChangeType(value, typeof(T));
                       }
                   }
                   catch (Exception)
                   {
                       returnValue = default(T);
                   }

               return returnValue;
           }
Pranay Deep
quelle
IMHO ist dies die bessere Antwort, da es auch den "nullable" -Aspekt enthält
Ole Albers
TypeDescriptorGibt es einen bestimmten Grund, warum Sie für nullbare Typen und Convert.ChangeTypefür nicht nullbare Typen verwenden? Dieser gesamte tryBlock kann nur auf TypeConverter2 Codezeilen reduziert werden und funktioniert sowohl für nullbar als auch für nicht nullbar.
IMujagic
8

sauberere Version von Pranays Antwort

public static T ConvertTo<T>(this object value)
{
    if (value is T variable) return variable;

    try
    {
        //Handling Nullable types i.e, int?, double?, bool? .. etc
        if (Nullable.GetUnderlyingType(typeof(T)) != null)
        {
            return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
        }

        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch (Exception)
    {
        return default(T);
    }
}
Eonasdan
quelle
0

In .NET gibt es einige Konventionen zum Konvertieren von Objekten eines Typs in einen anderen.

Diese Methoden sind jedoch viel langsamer als die typischen T.Parse(string), verursachen Boxen und beinhalten jedes Mal viele Zuordnungen, wenn Sie einen einzelnen Wert konvertieren möchten.

Für ValueString habe ich mich entschieden, eine geeignete statische Analysemethode des Typs mithilfe von Reflection zu finden, einen Lambda-Ausdruck zu erstellen, der ihn aufruft, und den kompilierten Delegaten für die zukünftige Verwendung zwischenzuspeichern ( ein Beispiel finden Sie in dieser Antwort ).

Es greift auch auf die oben erwähnten Methoden zurück, wenn der Typ keine geeignete Analysemethode hat (siehe Abschnitt Leistung in der Readme-Datei).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Şafak Gür
quelle