10
votes

Une autre prise sur FirstODEDefault

La méthode d'extension iEnumerable FirstArdefault n'a pas exactement ce que je le voulais, alors j'ai créé FirstOrValue. Est-ce un bon moyen d'y aller ou y a-t-il une meilleure façon?

public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, T value)
{
    T first = source.FirstOrDefault(predicate);
    return Equals(first, default(T)) ? value : first;
}


0 commentaires

4 Réponses :


5
votes

par défaut (t) code> retournera null code> par défaut pour les types de référence.

Je ferais ce p>

public static T FirstOrValue<T>(this IEnumerable<T> source, Func<T, bool> predicate, T value)
{
    T first = source.FirstOrDefault(predicate);
    return first ?? value;
}


4 commentaires

Je vais juste l'écrire sur une seule ligne: Retour Source.FirstTordefault (prédicat) ?? valeur;


@ZOTE: Faire de la manière Daniels, c'est plus facile de joindre un débogueur et de voir ce qui se passe


Mais cela ne fonctionnera pas comme ?? ne peut être utilisé que sur des types nullables.


Ne fonctionnera pas non plus si NULL est un élément valide de votre collection.



-1
votes

semble raisonnable pour moi si vous souhaitez modifier la lisibilité au lieu d'utiliser la défaillanceIfrempty.

Vous pouvez également créer un remplacement qui utilise une Lambda si la création de la valeur par défaut est chère, ce qui ne le crée que si nécessaire. xxx


1 commentaires

Très bien, l'ajout d'un lambda le rend encore plus utile.



42
votes

Votre code est probablement incorrect; Vous n'avez probablement pas considéré tous les cas.

Bien sûr, nous ne pouvons pas savoir si un code est correct ou incorrect jusqu'à ce que nous ayons une spécification. Alors commencez par écrire une spécification d'une ligne: p>

" firstorValue code> prend une séquence de t, un prédicat et une valeur de t, et renvoie soit le premier élément Dans la séquence qui correspond au prédicat s'il en existe un ou, s'il n'y en a pas, la valeur indiquée. " P>

Votre tentative est-elle en train de mettre en œuvre cette spécification? Certainement pas! Testez-le: P>

public static T FirstOrValue<T>(this IEnumerable<T> sequence, Func<T, bool> predicate, T value)
{
    if (sequence == null) throw new ArgumentNullException("sequence");
    if (predicate == null) throw new ArgumentNullException("predicate");
    foreach(T item in sequence)
        if (predicate(item)) return item;
    return value;
}


1 commentaires

Cela devrait faire partie du cadre! Ou ai-je oublié ça?



0
votes

Comme il s'agit d'une surcharge, il convient de mentionner la version sans prédicat.

public static T FirstOrValue<T>(this IEnumerable<T> sequence, T value)
{
    if (sequence == null) throw new ArgumentNullException("sequence");
    foreach(T item in sequence) 
        return item; 
    return value;
}


3 commentaires

Supposons que la séquence ait un million d'articles dedans et pas de propriété compte. Vous allez énumérer tout d'entre eux pour déterminer qu'il n'y a pas Aucun d'entre eux. Si vous avez un million de centimes dans un pot, et que vous souhaitez savoir si le pot est vide, comptez-vous les pennies? C'est une technique très très mauvaise que vous utilisez ici. (Il n'est pas non plus clair pour moi pourquoi vous affichez des réponses à une question de six ans qui a déjà une réponse correcte acceptée et ne répondent même pas même à la question initiale; peut-être qu'il y a une autre façon que vous puissiez ajouter plus de valeur sur le site?)


Je cherchais un FirstOrvalue et je suis tombé sur votre belle réponse. J'ai copié votre code et cela m'a eu lieu, il y a une surcharge. Collé cela ici au cas où d'autres ont traversé le même processus de pensée. Peut-être que vous pourriez suggérer une meilleure façon de le faire.


Eh bien, étant donné que votre méthode proposée est la même que celle que j'ai écrite sauf sans prédicat, ma suggestion serait d'écrire la même méthode sans prédicat: Statique Public Static T FirstOrvalue (Cette séquence iEnumerable T valeur T) {si (séquence == null) jette une nouvelle erreur d'argumentation ("séquence"); foreach (T item in séquence) article de retour; Valeur de retour; }