Ich versuche, eine generische Erweiterung zu erstellen, die 'TryParse' verwendet, um zu überprüfen, ob eine Zeichenfolge ein bestimmter Typ ist:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
Dies wird nicht kompiliert, da das Symbol 'TryParse' nicht aufgelöst werden kann.
Soweit ich weiß, ist 'TryParse' nicht Teil einer Schnittstelle.
Ist das überhaupt möglich?
Aktualisieren:
Mit den folgenden Antworten habe ich Folgendes gefunden:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
Es funktioniert ganz gut, aber ich denke, Ausnahmen auf diese Weise zu verwenden, fühlt sich für mich nicht richtig an.
Update2:
Geändert, um den Typ zu übergeben, anstatt Generika zu verwenden:
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
protected Boolean TryParse<T>(Object value, out T result) { result = default(T); var convertor = TypeDescriptor.GetConverter(typeof(T)); if (convertor == null || !convertor.IsValid(value)) { return false; } result = (T)convertor.ConvertFrom(value); return true; }
ConvertFrom(value)
Methode in einentry-catch
Block einschließen, um die Ausnahmen zu fangen.Antworten:
Sie sollten die TypeDescriptor- Klasse verwenden:
quelle
Ich habe kürzlich auch ein generisches TryParse benötigt. Folgendes habe ich mir ausgedacht:
Dann geht es einfach darum, so zu rufen:
quelle
T
Ich bin erst Monate später wieder auf diesen Beitrag gestoßen und habe bei der erneuten Verwendung festgestellt, dass die Methode nicht vom Handler abgeleitet werden kann, und wir müssen explizit angeben,T
wann wir ihn aufrufen. Ich bin neugierig, warum kann es nicht schließenT
?SomeMethod(TryParse<int>(DollarTextbox.Text, int.TryParse))
ohne eine Ausgabevariable zu erstellen, aus der das Ergebnis abgerufen werden kannint.TryParse
. Ich stimme jedoch Nicks Meinung zu, dass die Funktion auf den Typ schließen lässt.Die Verwendung von try / catches zur Flusskontrolle ist eine schreckliche Richtlinie. Das Auslösen einer Ausnahme führt zu Leistungsverzögerungen, während die Laufzeit die Ausnahme umgeht. Überprüfen Sie stattdessen die Daten vor der Konvertierung.
quelle
converter != null
die immer wahr ist, sodass sie aus dem Code entfernt werden kann.Wenn Sie TryParse verwenden möchten, können Sie Reflection wie folgt verwenden:
quelle
Type.GetType(string.Format(...))
mittype.MakeByRefType()
.Dies verwendet einen statischen Konstruktor für jeden generischen Typ, sodass er nur die teure Arbeit erledigen muss, wenn Sie ihn zum ersten Mal für einen bestimmten Typ aufrufen. Es behandelt alle Typen im System-Namespace, die über TryParse-Methoden verfügen. Es funktioniert auch mit nullbaren Versionen von jedem dieser (das sind Strukturen) mit Ausnahme von Aufzählungen.
quelle
Wie wäre es mit so etwas?
http://madskristensen.net/post/Universal-data-type-checker.aspx ( Archiv )
Dies kann ziemlich einfach in eine generische Methode konvertiert werden.
quelle
catch { }
. In diesem Fall gibt es jedoch keine Alternative, da .NET im Falle eines KonvertierungsfehlersBaseNumberConverter
dieException
Basisklasse auslöst. Das ist sehr unglücklich. Tatsächlich gibt es noch einige Stellen, an denen dieser Basistyp geworfen wird. Hoffentlich wird Microsoft diese in einer zukünftigen Version des Frameworks beheben.Sie können es nicht für allgemeine Typen tun.
Sie können eine Schnittstelle ITryParsable erstellen und für benutzerdefinierte Typen verwenden, die diese Schnittstelle implementieren.
Ich denke jedoch, dass Sie beabsichtigen, dies mit Grundtypen wie
int
und zu verwendenDateTime
. Sie können diese Typen nicht ändern, um neue Schnittstellen zu implementieren.quelle
dynamic
Schlüsselwort standardmäßig nicht , da es bei statischer Typisierung nicht funktioniert. Sie können Ihr eigenes dynamisches Objekt erstellen, das dies verarbeiten kann, dies ist jedoch nicht die Standardeinstellung.Inspiriert von der hier von Charlie Brown veröffentlichten Lösung habe ich mithilfe von Reflection ein generisches TryParse erstellt, das optional den analysierten Wert ausgibt:
Es kann so genannt werden:
Update:
Auch dank der Lösung von YotaXP, die mir sehr gefällt, habe ich eine Version erstellt, die keine Erweiterungsmethoden verwendet, aber dennoch einen Singleton hat, wodurch die Notwendigkeit einer Reflexion minimiert wird:
Nennen Sie es so:
quelle
Ziemlich spät zur Party, aber hier ist, was ich mir ausgedacht habe. Keine Ausnahmen, einmalige (pro Typ) Reflexion.
Die zusätzliche Klasse ist erforderlich, da Erweiterungsmethoden in generischen Klassen nicht zulässig sind. Dies ermöglicht eine einfache Verwendung, wie unten gezeigt, und trifft die Reflexion nur bei der ersten Verwendung eines Typs.
quelle
Hier ist eine weitere Option.
Ich habe eine Klasse geschrieben, die es einfach macht, eine beliebige Anzahl von
TryParse
Handlern zu registrieren . Damit kann ich Folgendes tun:Ich werde
42
auf die Konsole gedruckt.Die Klasse ist:
quelle
Wenn ich fast genau das tun wollte, musste ich es auf die harte Tour umsetzen, wenn ich darüber nachdachte. Geben Sie eine oder Methode
T
antypeof(T)
und suchen Sie sie, wenn Sie sie gefunden haben.TryParse
Parse
quelle
Das ist mein Versuch. Ich habe es als "Übung" gemacht. Ich habe versucht, es so ähnlich wie die vorhandenen " Convert.ToX () " -ones usw. zu machen. Aber dies ist eine Erweiterungsmethode:
quelle
TypeConverter.ConvertFrom()
ist , dass die Source - Klasse die Typumwandlung zur Verfügung stellen muss, die in der Regel bedeutet , dass Sie nicht Umstellung auf benutzerdefinierte Typen unterstützen kann.Wie Sie sagten,
TryParse
ist nicht Teil einer Schnittstelle. Es ist auch kein Mitglied einer bestimmten Basisklasse, da es tatsächlich iststatic
undstatic
Funktionen nicht sein könnenvirtual
. Der Compiler kann also nicht sicherstellen, dassT
tatsächlich ein Mitglied aufgerufenTryParse
wird. Dies funktioniert also nicht.Wie @Mark sagte, können Sie Ihre eigene Benutzeroberfläche erstellen und benutzerdefinierte Typen verwenden, aber Sie haben kein Glück mit den integrierten Typen.
quelle
quelle
Dies ist eine Frage der "allgemeinen Einschränkungen". Da Sie keine bestimmte Benutzeroberfläche haben, stecken Sie fest, es sei denn, Sie folgen den Vorschlägen der vorherigen Antwort.
Eine Dokumentation hierzu finden Sie unter folgendem Link:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
Es zeigt Ihnen, wie Sie diese Einschränkungen verwenden, und sollte Ihnen weitere Hinweise geben.
quelle
Ausgeliehen von http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx
Wenn Sie dieser Referenz folgen: Wie rufe ich eine statische Methode in C # 4.0 mit dynamischem Typ auf?
Und verwenden Sie es wie folgt:
quelle
Ich habe es geschafft, etwas zu bekommen, das so funktioniert
Hier ist mein Code
Der StaticMembersDynamicWrapper wurde aus dem Artikel von David Ebbo übernommen (er hat eine AmbiguousMatchException ausgelöst ).
quelle
quelle
Mit
TypeDescriptor
Klassenverwendung inTryParse
verwandter Weise:quelle
Mit den obigen Informationen habe ich Folgendes entwickelt. Es wird das Objekt direkt konvertieren ist möglich, andernfalls wird das Objekt in eine Zeichenfolge konvertiert und die TryParse-Methode für den gewünschten Objekttyp aufgerufen.
Ich speichere die Methoden in einem Wörterbuch zwischen, wobei jede gefunden wird, um die Last beim Abrufen von Methoden zu verringern.
Es ist möglich zu testen, ob das Objekt direkt in den Zieltyp konvertiert werden kann, wodurch der Teil der Zeichenfolgenkonvertierung weiter reduziert würde. Aber das werde ich vorerst weglassen.
quelle
Ich habe hier eine Reihe von Ideen zusammengestellt und eine sehr kurze Lösung gefunden.
Dies ist eine Erweiterungsmethode für eine Zeichenfolge
Ich habe es mit dem gleichen Footprint wie die TryParse-Methoden für die numerischen Typen erstellt
'' '
quelle
T.TryParse ... warum?
Ich sehe keinen Vorteil in einer solchen generischen
TryParse
Funktion. Es gibt zu viele verschiedene Strategien zum Parsen und Konvertieren von Daten zwischen verschiedenen Typen mit möglicherweise widersprüchlichem Verhalten. Wie kann diese Funktion wissen, welche Strategie kontextfrei gewählt werden soll?Convert.ChangeType
. Diese API kann zur Laufzeit angepasst werden. Erfordert Ihre Funktion ein Standardverhalten oder ermöglicht sie eine Anpassung?quelle
Eine Version zum Abrufen von Nachkommen von XDocument.
quelle