Sélectionnez analysé int, si la chaîne a été parseable à int
J'ai donc une IEnumerable<string>
qui peuvent contenir des valeurs qui peuvent être analysés comme int
, ainsi que des valeurs qui ne peuvent pas être.
Comme vous le savez, Int32.Parse
déclenche une exception si une chaîne ne peut pas être changé pour un int, alors que Int32.TryParse
peut être utilisé pour vérifier et voir si la conversion est possible sans traiter l'exception.
Si je veux utiliser une requête LINQ pour one-liner analyser ces chaînes qui peut être analysé comme int, sans jeter une exception le long de la voie. J'ai une solution, mais voudrais l'avis de la communauté quant à savoir si c'est la meilleure approche.
Voici ce que j'ai:
int asInt = 0;
var ints = from str in strings
where Int32.TryParse(str, out asInt)
select Int32.Parse(str);
Donc, comme vous pouvez le voir, je suis en utilisant asInt
comme un espace de travail pour l'appel à la TryParse
, juste pour déterminer si TryParse
serait de réussir (return bool). Puis, dans la projection, je suis tout à fait d'effectuer l'analyse. Qui se sent moche.
Est-ce la meilleure manière de filtrer le parseable valeurs dans une ligne à l'aide de LINQ?
- Vous pouvez utiliser
asInt
directement en sélectionner une valeur. - Droit; ressemble à la réponse de Joe capture qui. J'ai effectivement changé à mes accepté de répondre parce que c'est plus concis que certains des autres.
Vous devez vous connecter pour publier un commentaire.
Il est difficile de le faire que dans la syntaxe de la requête, mais c'est pas trop mal à lambda syntaxe:
Alternativement, vous pouvez le trouver en valeur l'écriture d'une méthode qui retourne un
int?
:Vous pouvez simplement utiliser:
C'est toujours deux codelines, mais vous pouvez raccourcir votre original un peu:
Depuis le TryParse fonctionne déjà au moment de la sélection, la
asInt
de la variable est rempli, de sorte que vous pouvez l'utiliser comme valeur de retour - vous n'avez pas besoin d'analyser de nouveau.Si vous n'avez pas l'esprit de vos collègues de travail le saut, vous dans le stationnement, il y a un moyen de le faire à une véritable ligne de linq (pas de points-virgules) ....
Il n'est pas pratique, mais, ce faisant, dans une déclaration était bien trop intéressant, un défi pour la laisser passer.
J'aurais probablement ce petit utilitaire méthode quelque part (en fait, je le fais dans mon actuel de la base de code :-))
Puis vous utilisez ce beaucoup plus propre LINQ déclaration:
Je ferais c'est de LINQ-to-objets:
Puis dans la requête:
Si vous souhaitez définir une méthode d'extension pour ce faire, je serais de créer une solution globale qui est simple à utiliser, au lieu de vous obliger à écrire une nouvelle null en cas d'échec de l'enveloppe pour chaque essai, la fonction, et vous oblige à filtrer les valeurs null.
Utilisation:
C'est un peu bizarre que le C# ne pouvez pas déduire
SelectTry
's de type générique arguments.(
TryFunc
's TResult ne peut pas être covariantes (c'est à direout TResult
) commeFunc
. Comme Eric Lippert explique les paramètres de sortie sont en fait juste paramètres de ref avec la fantaisie d'écrire avant de lire les règles.)Inspiré par Carl Walsh réponse, j'ai pris un peu plus loin pour permettre l'analyse de propriétés:
Voici un exemple qui peut également être trouvé dans ce violon:
De sortie de ce programme:
Si vous êtes à la recherche d'une ligne d'expression Linq et fine avec l'allocation d'un nouvel objet sur chaque boucle, j'utiliserais le plus puissant SelectMany à le faire avec une seule Linq appel
Je suis d'accord que l'utilisation de la variable supplémentaire se sent laid.
Basé sur Jon répondre et la mise à jour vers C# 7.0 solutions on peut utiliser la nouvelle
var out
fonctionnalité: (pas beaucoup plus courte, mais pas besoin pour un intérieur de la portée ou de la requête variables temp)et avec uplets nommé:
Ou si ce qui suggère une méthode pour l'utilisation de la syntaxe de la requête:
J'aimerais également proposer une syntaxe de requête sans une méthode supplémentaire pour elle, mais comme expliqué dans le lien suivant
out var
n'est pas pris en charge par le c# 7.0 et les résultats dans l'erreur de compilation:Le lien: L'Expression des variables dans les expressions de requête
Par le biais de ce C# 7.0 fonctionnalité, on peut le faire fonctionner sur plus tôt .NET versions:
var numbers = values.Select(x => int.TryParse(x, out int value) ? (int?) value : null);
IEnumerable<int>
et pasIEnumerable<int?>
et dans le but de le faire avec votre suggestion que j'avais aussi besoin d'ajouterWhere(x => x != null) and to convert to
int` au lieu deint?