163 votes

Qu'est-ce qu'un prédicat en C# ?

Je suis très novice dans l'utilisation des prédicats et je viens d'apprendre à écrire :

Predicate<int> pre = delegate(int a){ a %2 == 0 };

Que retournera le prédicat, et en quoi est-il utile en programmation ?

462voto

Dan Tao Points 60518

Predicate<T> est une construction fonctionnelle qui fournit un moyen pratique de tester si quelque chose est vrai dans un cas donné. T objet.

Par exemple, supposons que j'ai une classe :

class Person {
    public string Name { get; set; }
    public int Age { get; set; }
}

Maintenant, disons que j'ai un List<Person> people et je veux savoir s'il y a un certain Oscar dans la liste.

Sans en utilisant un Predicate<Person> (ou Linq, ou n'importe lequel de ces trucs sophistiqués), je pourrais toujours accomplir ceci en faisant ce qui suit :

Person oscar = null;
foreach (Person person in people) {
    if (person.Name == "Oscar") {
        oscar = person;
        break;
    }
}

if (oscar != null) {
    // Oscar exists!
}

C'est bien, mais disons que je veux vérifier s'il existe une personne nommée "Ruth" ? Ou une personne dont l'âge est 17 ?

Utilisation d'un Predicate<Person> je peux trouver ces choses en utilisant beaucoup moins de code :

Predicate<Person> oscarFinder = (Person p) => { return p.Name == "Oscar"; };
Predicate<Person> ruthFinder = (Person p) => { return p.Name == "Ruth"; };
Predicate<Person> seventeenYearOldFinder = (Person p) => { return p.Age == 17; };

Person oscar = people.Find(oscarFinder);
Person ruth = people.Find(ruthFinder);
Person seventeenYearOld = people.Find(seventeenYearOldFinder);

Remarquez que j'ai dit beaucoup moins de code pas beaucoup plus rapide . Une idée fausse très répandue chez les développeurs est que si quelque chose prend une ligne, il doit être plus performant que quelque chose qui prend dix lignes. Mais dans les coulisses, le Find qui prend un Predicate<T> n'est qu'une énumération après tout. Il en va de même pour une grande partie des fonctionnalités de Linq.

Examinons donc le code spécifique de votre question :

Predicate<int> pre = delegate(int a){ return a % 2 == 0; };

Ici, nous avons un Predicate<int> pre qui prend un int a et retourne a % 2 == 0 . Il s'agit essentiellement de tester un nombre pair. Ce qui veut dire que :

pre(1) == false;
pre(2) == true;

Et ainsi de suite. Cela signifie également que, si vous avez un List<int> ints et que tu veux trouver le premier nombre pair, tu peux juste faire ça :

int firstEven = ints.Find(pre);

Bien sûr, comme pour tout autre type que vous pouvez utiliser dans le code, c'est une bonne idée de donner à vos variables des noms descriptifs ; ainsi, je conseillerais de modifier l'exemple ci-dessus pre à quelque chose comme evenFinder ou isEven -- ou quelque chose de ce genre. Alors le code ci-dessus est beaucoup plus clair :

int firstEven = ints.Find(evenFinder);

43voto

Reed Copsey Points 315315

Le prédicat renvoie toujours un booléen, par définition.

Predicate<T> est fondamentalement identique à Func<T,bool> .

Les prédicats sont très utiles en programmation. Ils sont souvent utilisés pour vous permettre de fournir une logique au moment de l'exécution, qui peut être aussi simple ou aussi compliquée que nécessaire.

Par exemple, WPF utilise un Predicate<T> comme entrée pour le filtrage de l'ICollectionView d'une ListView. Cela vous permet d'écrire une logique qui peut retourner un booléen déterminant si un élément spécifique doit être inclus dans la vue finale. La logique peut être très simple (il suffit de renvoyer un booléen sur l'objet) ou très complexe, c'est vous qui décidez.

16voto

Brahim Boulkriat Points 351

Le code suivant peut vous aider à comprendre certaines utilisations réelles des prédicats (combinés avec des itérateurs nommés).

namespace Predicate
{
    class Person
    {
        public int Age { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            foreach (Person person in OlderThan(18))
            {
                Console.WriteLine(person.Age);
            }
        }

        static IEnumerable<Person> OlderThan(int age)
        {
            Predicate<Person> isOld = x => x.Age > age;
            Person[] persons = { new Person { Age = 10 }, new Person { Age = 20 }, new Person { Age = 19 } };

            foreach (Person person in persons)
                if (isOld(person)) yield return person;
        }
    }
}

14voto

osij2is Points 501

En C#, les prédicats sont simplement des délégués qui renvoient des booléens. Elles sont utiles (d'après mon expérience) lorsque vous cherchez dans une collection d'objets et que vous voulez quelque chose de spécifique.

J'ai récemment rencontré ces problèmes lors de l'utilisation de contrôles Web tiers (comme les arborescences). Ainsi, lorsque j'ai besoin de trouver un nœud dans un arbre, j'utilise la méthode .Find() et je passe un prédicat qui renvoie le nœud spécifique que je recherche. Dans votre exemple, si 'a' mod 2 est égal à 0, le délégué renverra true. En fait, lorsque je cherche un nœud dans un arbre, je compare son nom, son texte et sa valeur pour trouver une correspondance. Lorsque le délégué trouve une correspondance, il renvoie le nœud spécifique que je recherchais.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X