J'essaie de créer une extension générique qui utilise «TryParse» pour vérifier si une chaîne est d'un type donné:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
cela ne se compilera pas car il ne peut pas résoudre le symbole 'TryParse'
Si je comprends bien, «TryParse» ne fait partie d'aucune interface.
Est-ce possible de faire du tout?
Mettre à jour:
En utilisant les réponses ci-dessous, j'ai trouvé:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
Cela fonctionne assez bien, mais je pense que l'utilisation d'exceptions de cette manière ne me semble pas appropriée.
Update2:
Modifié pour passer le type plutôt que d'utiliser des génériques:
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)
méthode dans untry-catch
bloc pour intercepter les exceptions.Réponses:
Vous devez utiliser la classe TypeDescriptor :
la source
J'ai également récemment eu besoin d'un TryParse générique. Voici ce que j'ai trouvé;
Il suffit alors d'appeler ainsi:
la source
T
j'ai remarqué en l'utilisant à nouveau que la méthode ne pouvait pas déduire du gestionnaire, et nous devons spécifier explicitementT
quand nous l'appelons. Je suis curieux, pourquoi ne peut-il pas en déduireT
?SomeMethod(TryParse<int>(DollarTextbox.Text, int.TryParse))
sans créer une variable de sortie pour attraper le résultatint.TryParse
. Cependant, je suis d'accord avec le sentiment de Nick d'avoir la fonction inférer le type.L'utilisation de try / catch pour le contrôle de flux est une politique terrible. La levée d'une exception entraîne des retards de performances pendant que le runtime contourne l'exception. Validez plutôt les données avant de les convertir.
la source
converter != null
est toujours vrai, donc il peut être supprimé du code.Si vous êtes prêt à utiliser TryParse, vous pouvez utiliser la réflexion et le faire comme ceci:
la source
Type.GetType(string.Format(...))
partype.MakeByRefType()
.Celui-ci utilise un constructeur statique pour chaque type générique, il n'a donc qu'à effectuer le travail coûteux la première fois que vous l'appelez sur un type donné. Il gère tous les types de l'espace de noms système qui ont des méthodes TryParse. Il fonctionne également avec les versions nullables de chacun de ceux-ci (qui sont des structures) à l'exception des énumérations.
la source
Que diriez-vous quelque chose comme ça?
http://madskristensen.net/post/Universal-data-type-checker.aspx ( Archives )
Cela peut être converti assez facilement en une méthode générique.
la source
catch { }
. Cependant, dans ce cas, il n'y a pas d'alternative, car le .NETBaseNumberConverter
lève laException
classe de base en cas d'erreur de conversion. C'est très malheureux. En fait, il y a encore pas mal d'endroits où ce type de base est lancé. Espérons que Microsoft les corrigera dans une future version du framework.Vous ne pouvez pas le faire sur des types généraux.
Ce que vous pourriez faire est de créer une interface ITryParsable et de l'utiliser pour des types personnalisés qui implémentent cette interface.
Je suppose cependant que vous avez l'intention de l'utiliser avec des types de base comme
int
etDateTime
. Vous ne pouvez pas modifier ces types pour implémenter de nouvelles interfaces.la source
dynamic
mot - clé, car cela ne fonctionnera pas sur la frappe statique. Vous pouvez créer votre propre objet dynamique qui peut gérer cela, mais ce n'est pas par défaut.Inspiré par la solution publiée ici par Charlie Brown, j'ai créé un TryParse générique à l'aide de la réflexion qui génère éventuellement la valeur analysée:
On peut l'appeler ainsi:
Mise à jour:
également grâce à la solution de YotaXP que j'aime beaucoup, j'ai créé une version qui n'utilise pas de méthodes d'extension mais qui a toujours un singleton, minimisant le besoin de faire de la réflexion:
Appelez ça comme ceci:
la source
Un peu tard pour la fête, mais voici ce que j'ai trouvé. Aucune exception, réflexion unique (par type).
La classe supplémentaire est requise car les méthodes d'extension ne sont pas autorisées dans les classes génériques. Cela permet une utilisation simple, comme illustré ci-dessous, et ne frappe la réflexion que la première fois qu'un type est utilisé.
la source
Voici une autre option.
J'ai écrit un cours qui facilite l'enregistrement d'un nombre illimité de
TryParse
illimité gestionnaires. Cela me permet de faire ceci:Je suis
42
imprimé sur la console.La classe est:
la source
Quand j'ai voulu faire presque exactement cette chose, j'ai dû l'implémenter à la dure, après réflexion. Étant donné
T
, réfléchisseztypeof(T)
et recherchez une méthodeTryParse
ouParse
, en l'invoquant si vous l'avez trouvée.la source
Ceci est mon essai. Je l'ai fait comme un "exercice". J'ai essayé de le rendre aussi similaire à utiliser que les existants " Convert.ToX () ", etc. Mais celui-ci est une méthode d'extension:
la source
TypeConverter.ConvertFrom()
est que la classe source doit fournir la conversion de type, ce qui signifie généralement que vous ne pouvez pas prendre en charge la conversion en types personnalisés.Comme vous l'avez dit,
TryParse
ne fait pas partie d'une interface. Il n'est pas non plus membre d'une classe de base donnée car il est en faitstatic
et lesstatic
fonctions ne peuvent pas l'êtrevirtual
. Donc, le compilateur n'a aucun moyen de s'assurer qu'unT
membre est réellement appeléTryParse
, donc cela ne fonctionne pas.Comme l'a dit @Mark, vous pouvez créer votre propre interface et utiliser des types personnalisés, mais vous n'avez pas de chance pour les types intégrés.
la source
la source
Il s'agit de «contraintes génériques». Parce que vous n'avez pas d'interface spécifique, vous êtes bloqué, sauf si vous suivez les suggestions de la réponse précédente.
Pour obtenir de la documentation à ce sujet, consultez le lien suivant:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
Il vous montre comment utiliser ces contraintes et devrait vous donner quelques indices supplémentaires.
la source
Emprunté de http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx
en suivant cette référence: Comment invoquer une méthode statique en C # 4.0 avec un type dynamique?
Et utilisez-le comme suit:
la source
J'ai réussi à obtenir quelque chose qui fonctionne comme ça
Voici mon code
Le StaticMembersDynamicWrapper est adapté de l' article de David Ebbo (il lançait une AmbiguousMatchException)
la source
la source
Avec l'
TypeDescriptor
utilisation de classe deTryParse
manière connexe:la source
En utilisant les informations ci-dessus, c'est ce que j'ai développé. Il convertira directement l'objet est possible, sinon il convertira l'objet en chaîne et appellera la méthode TryParse pour le type d'objet souhaité.
Je mets en cache les méthodes dans un dictionnaire à mesure que chacune est rencontrée pour réduire la charge de récupération des méthodes.
Il est possible de tester si l'objet peut être directement converti en type cible, ce qui réduirait davantage la partie de conversion de chaîne. Mais je vais laisser ça de côté pour l'instant.
la source
J'ai rassemblé un tas d'idées ici et je me suis retrouvé avec une solution très courte.
Il s'agit d'une méthode d'extension sur une chaîne
Je l'ai fait avec la même empreinte que les méthodes TryParse sur les types numériques
'' '
la source
T.TryParse ... pourquoi?
Je ne vois aucun avantage à avoir une telle
TryParse
fonction générique . Il existe trop de stratégies différentes pour analyser et convertir des données entre différents types, avec un comportement conflictuel possible. Comment cette fonction pourrait-elle savoir quelle stratégie choisir sans contexte?Convert.ChangeType
. Cette API est personnalisable au moment de l'exécution. Votre fonction nécessite-t-elle un comportement par défaut ou permet-elle une personnalisation?la source
Une version pour obtenir des descendants de XDocument.
la source