Comment puis-je convertir à un type spécifique dans une version générique de TryParse()?
J'ai le scénario suivant, où je veux passer en chaîne et d'un type générique:
public class Worker {
public void DoSomeWork<T>(string value)
where T : struct, IComparable<T>, IEquatable<T> { ... }
}
À un certain point le long du chemin j'ai besoin de convertir la chaîne de la valeur à ses T
valeur. Mais je ne veux pas faire un tout droit convertir que j'ai besoin de réaliser une certaine logique si la chaîne ne peut pas être convertie type T
.
Je pensais que je pourrais essayer d'utiliser Convert.ChangeType()
mais cela a le problème que si elle ne se convertit pas, il va lever une exception et je vais courir le DoSomeWork()
méthode assez souvent pour ne pas avoir à compter sur un try/catch pour déterminer si la conversion est valide.
Donc cela m'a fait penser, je sais que je vais travailler avec des types numériques, d'où T seront les suivantes: int
, uint
, short
, ushort
, long
, ulong
, byte
, sbyte
, decimal
, float
, double
. Sachant cela, j'ai pensé qu'il pourrait être possible de trouver une solution plus rapide de travail avec le fait que je sais que je vais être en utilisant les types numériques (remarque si T
n'est pas un type numérique, je lève une exception)...
public class NumericWorker {
public void DoSomeWork<T>(string value)
where T : struct, IComparable<T>, IEquatable<T>
{
ParseDelegate<T> tryConverter =
SafeConvert.RetreiveNumericTryParseDelegate<T>();
...
}
}
public class SafeConvert
{
public delegate bool ParseDelegate<T>(string value, out T result);
public static ParseDelegate<T> RetreiveNumericTryParseDelegate<T>()
where T : struct, IComparable<T>, IEquatable<T>
{
ParseDelegate<T> tryParseDelegate = null;
if (typeof(T) == typeof(int))
{
tryParseDelegate = (string v, out T t) =>
{
int typedValue;
bool result = int.TryParse(v, out typedValue);
t = result ? (T)typedValue : default(T);
//(T)Convert.ChangeType(typedValue, typeof(T)) : default(T);
return result;
};
}
else if (typeof(T) == typeof(uint)) { ... }
else if (typeof(T) == typeof(short)) { ... }
else if (typeof(T) == typeof(ushort)) { ... }
else if (typeof(T) == typeof(long)) { ... }
else if (typeof(T) == typeof(ulong)) { ... }
else if (typeof(T) == typeof(byte)) { ... }
else if (typeof(T) == typeof(sbyte)) { ... }
else if (typeof(T) == typeof(decimal)) { ... }
else if (typeof(T) == typeof(float)) { ... }
else if (typeof(T) == typeof(double)) { ... }
return tryParseDelegate;
}
}
Mais le ci-dessus a le problème que je ne peux pas écrire t = result ? (T)typedValue : default(T);
que le casting de typedValue
à T
causes des problèmes et le seul moyen que j'ai été en mesure de se déplacer jusqu'ici, il est en écrivant (T)Convert.ChangeType(typedValue, typeof(T))
. Mais si je fais cela, je suis juste entrain de faire une convertir.
Donc je me demandais si quelqu'un sait comment je pourrais résoudre ce problème (si vous pensez à faire le ChangeType()
est un problème) ou si il y a une meilleure solution totalement que je n'ai pas considéré.
Vous devez vous connecter pour publier un commentaire.
Essayer:
Oui, les génériques peuvent être un peu ennuyeux à certains moments.
FWIW, je l'utilise beaucoup plus simple wrapper autour de
Convert.ChangeType()
qui a juste fait un pré-contrôle des chaînes vides. Sauf si vous utilisez ce pour non cochée la saisie de l'utilisateur, qui va probablement être assez.ChangeType()
, mais si vous êtes préoccupé par le style, ta solution a l'air bien. Notez que vous pourriez probablement simplement l'API en la faisant bouillir le bas à une seule méthode générique, où T est spécifié implicitement par l'out
paramètre.Donné ceci:
Je recommande simplement à l'aide Convertir.ChangeType, et ne pas se soucier à ce sujet. La seule fois où vous aurez une exception est lorsque votre chaîne est misformatted, dans ce cas, vous pouvez le retourner par défaut(T).
ie:
ToType d'être le paramètre générique ici. Cela fonctionne pour les types nullables, juste au cas où vous en avez besoin. Vous pouvez extraire votre méthode principale d'être un convertisseur générique, qui permettra de convertir n'importe quel type, y compris nullable.
Vous pouvez essayer quelque chose de simple
Pourquoi ne pas utiliser de réflexion et d'utiliser le construit en TryParse méthodes? Joli beaucoup un pour chaque type natif, à l'exception de Guid.