web-dev-qa-db-fra.com

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 va renvoyer le prédicat, et en quoi est-il utile lors de la programmation?

161
Jebli

Predicate<T> est une construction fonctionnelle offrant un moyen pratique de tester si quelque chose est vrai pour un objet T donné.

Par exemple, supposons que j'ai un cours:

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 une personne nommée 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 cela en procédant comme suit:

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

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

C'est bon, mais alors disons que je veux vérifier s'il y a une personne nommée "Ruth"? Ou une personne de 17 ans?

Utilisant 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 beaucoup parlé moins de code, pas beaucoup plus rapide. Une idée fausse commune aux développeurs est que si quelque chose prend une ligne, il doit être plus performant que quelque chose qui prend dix lignes. Mais en coulisse, la méthode Find, qui prend un Predicate<T>, ne fait qu’énumérer après tout. La même chose est vraie pour beaucoup de fonctionnalités de Linq.

Voyons 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. Ceci consiste essentiellement à tester un nombre pair. Cela signifie:

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

Etc. Cela signifie aussi, si vous avez un List<int> ints et que vous voulez trouver le premier numéro pair, vous pouvez simplement faire ceci:

int firstEven = ints.Find(pre);

Bien sûr, comme avec tout autre type que vous pouvez utiliser dans le code, c'est une bonne idée de donner à vos variables des noms descriptifs; Je vous conseillerais donc de remplacer le pre ci-dessus par quelque chose comme evenFinder ou isEven - quelque chose du genre. Alors le code ci-dessus est beaucoup plus clair:

int firstEven = ints.Find(evenFinder);
450
Dan Tao

Le prédicat retournera 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 d'ICollectionView d'un ListView. Cela vous permet d'écrire une logique pouvant renvoyer 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, à vous de décider.

43
Reed Copsey

Le code suivant peut vous aider à comprendre certaines utilisations du prédicat dans le monde réel (associé à 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;
        }
    }
}
16
Brahim Boulkriat

En C #, les prédicats sont simplement des délégués qui retournent des booléens. D'après mon expérience, ils sont utiles lorsque vous effectuez une recherche dans une collection d'objets et souhaitez quelque chose de spécifique.

Je les ai récemment rencontrés lors de l’utilisation de contrôles Web tiers (comme des arborescences), donc lorsque je dois trouver un nœud dans une arborescence, j’utilise la méthode .Find () et passe un prédicat qui renvoie le nœud spécifique que je suis. à la recherche de. Dans votre exemple, si 'a' mod 2 est à 0, le délégué retournera true. Certes, lorsque je recherche un nœud dans une arborescence, je compare ses propriétés nom, texte et valeur pour une correspondance. Lorsque le délégué trouve une correspondance, il renvoie le nœud spécifique que je cherchais.

14
osij2is