2
votes

Renvoyer la valeur du modificateur out à une collection en C #

Supposons que je reçoive une collection de chaînes de l'utilisateur. Je dois les convertir en séquences GUID pour un traitement ultérieur. Il est possible que l'utilisateur entre des données non valides (séquence GUID incorrecte), je dois donc valider l'entrée. De plus, je peux exécuter un processus métier si seules toutes les données téléchargées sont des valeurs GUID correctes. Voici mon code:

IEnumerable<string> userUploadedValues = /* some logic */;
bool canParseUserInputToGuid = userUploadedValues.All(p => Guid.TryParse(p, out var x));
if(canParseUserInputToGuid)
    var parsedUserInput = userUploadedValues.Select(p=> Guid.Parse(p));

Cette logique fonctionne plutôt bien, mais je ne l'aime pas car en fait je travaille deux fois. En deuxième ligne, Guid.TryParse (p, out var x) écrit déjà la séquence GUID analysée dans la variable X. Existe-t-il une approche pour combiner la logique de validation et de mappage - si les éléments de séquence satisfont à la condition ( Tous ), mappez ces éléments à une nouvelle collection ( Select ) dans une requête? C'est aussi important pour moi en termes de performances, car il est possible que le client envoie une grande quantité de données (1, 000, 000+ éléments) et faire deux fois le travail ici est un peu inefficace.


1 commentaires

Vous n'avez pas besoin d'utiliser LINQ partout.


4 Réponses :


2
votes

Vous pouvez faire quelque chose comme ça dans un seul Select:

var parsedUserInput2 = userUploadedValues.Select(p => p.ToGuid())
                                         .Where(p => p != null);

Pour celui-ci, vous devez vous assurer qu'il n'y a pas de Guid. entrée de l'utilisateur.

Sinon, vous pouvez renvoyer un Guid nullable si l'analyse échoue:

public static class MyExtensions
{
    public static Guid? ToGuid(this string arg)
    {
        Guid? result = null;
        if(Guid.TryParse(arg, out Guid guid))
            result = guid;
        return result;
    }
}

Une autre solution en créant une méthode d'extension, par exemple:

var parsedUserInput = userUploadedValues.Select(p => Guid.TryParse(p, out var x) ? x : default(Guid?))
                                        .Where(p => p != null);

et l'utilisation:

var parsedUserInput = userUploadedValues.Select(p => Guid.TryParse(p, out var x) ? x : default)
                                        .Where(p => p != default);

Mais restez dans sachez que dans ce cas, vous aurez une collection de Guids nullables.


4 commentaires

Cela supprimera cependant toutes les valeurs correctement spécifiées de default (Guid).


@JonSkeet Correct, cela sera utile s'il est nécessaire que guid ne soit pas celui par défaut / vide.


@JonSkeet En quelque sorte mis à jour, mais je ne suis pas sûr des performances ici.


Je ne m'attendrais pas à une différence de performance particulière ici. Vous pouvez toujours modifier votre Select d'origine en simplement: .Select (p => Guid.TryParse (p, out var x)? X: default (Guid?)) that cela aurait le résultat équivalent.



1
votes

Votre variable out var x sera Guid.Empty dans le cas où ce n'est pas un Guid valide. Vous pouvez donc simplement faire ceci:

    IEnumerable<string> userUploadedValues = new[]
    {
        "guids.."
    };
    var maybeGuids = userUploadedValues.Select( x => {
                                                    Guid.TryParse( x, out var @guid );
                                                    return @guid;
                                                } );
    if ( maybeGuids.All( x => x != Guid.Empty ) )
    {
        //all the maybe guids are guids
    }


1 commentaires

Sauf que vous rejetez toutes les valeurs Guid.Empty explicitement spécifiées .



1
votes

Vous pouvez optimiser la validation et la conversion comme ci-dessous,

IEnumerable<string> userUploadedValues = /* some logic */;
var parsedGuids = userUploadedValues.Where(p => Guid.TryParse(p, out var x));
if(userUploadedValues.Count() != parsedGuids.Count())
{
    //Some conversion failed, 
}

Si le nombre des deux listes est identique, alors vous avez tous les GUID convertis dans les parsedGuids.

p>


0 commentaires

1
votes

Parfois, la méthode non LINQ est simplement plus facile à lire et non plus.

var parsedUserInput = new List<string>();
foreach(var value in userUploadedValues)
{
    if (Guid.TryParse(value, out var x)) parsedUserInput.Add(x);
    else...
}


0 commentaires