Co to jest predykat w c#? [duplikat]

To pytanie ma już odpowiedź tutaj:

Jestem nowy w używaniu predykatów i właśnie nauczyłem się pisać:

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

Co zwróci predykat i jak jest przydatny podczas programowania?

Author: BradleyDotNET, 2009-11-10

4 answers

Predicate<T> jest konstrukcją funkcjonalną zapewniającą wygodny sposób sprawdzenia, czy coś jest prawdą o danym obiekcie T.

Na przykład załóżmy, że mam klasę:

class Person {
    public string Name { get; set; }
    public int Age { get; set; }
}
Powiedzmy, że mam kogoś o imieniu Oscar.

bez za pomocą Predicate<Person> (lub Linq, lub cokolwiek z tych fantazyjnych rzeczy), zawsze mogłem to osiągnąć, wykonując następujące czynności:

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

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

To jest w porządku, ale powiedzmy, że chcę sprawdź, czy istnieje osoba o imieniu "Ruth"? Albo osoba, która ma 17 lat?

Używając Predicate<Person>, mogę znaleźć te rzeczy używając dużo mniej kodu:

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);

Zauważ, że powiedziałem dużo mniej kodu , nie dużo szybciej . Częstym błędnym przekonaniem programistów jest to, że jeśli coś zajmuje jedną linię, musi działać lepiej niż coś, co zajmuje dziesięć linii. Ale za kulisami metoda Find, która zajmuje Predicate<T>, jest po prostu wyliczaniem. To samo dotyczy wielu Funkcjonalność Linq.

Przyjrzyjmy się więc konkretnemu kodowi w twoim pytaniu:]}
Predicate<int> pre = delegate(int a){ return a % 2 == 0; };

Tutaj mamy Predicate<int> pre, który pobiera int a i zwraca a % 2 == 0. Jest to zasadniczo test dla liczby parzystej. Oznacza to:

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

I tak dalej. Oznacza to również, że jeśli masz List<int> ints i chcesz znaleźć pierwszą liczbę parzystą, możesz to zrobić:

int firstEven = ints.Find(pre);

Oczywiście, jak w przypadku każdego innego typu, którego można użyć w kodzie, dobrym pomysłem jest podanie swojego zmienne nazwy opisowe; radzę więc zmienić powyższe pre na coś w rodzaju evenFinder lub isEven -- coś w tym stylu. Następnie powyższy kod jest o wiele jaśniejszy:

int firstEven = ints.Find(evenFinder);
 413
Author: Dan Tao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-10 19:24:04

Predykat zawsze zwróci wartość logiczną z definicji.

Predicate<T> jest w zasadzie identyczna z Func<T,bool>.

Predykaty są bardzo przydatne w programowaniu. Są one często używane, aby umożliwić dostarczenie logiki w czasie wykonywania, które mogą być tak proste lub tak skomplikowane, jak to konieczne.

Na przykład WPF używa Predicate<T> jako wejścia do filtrowania widoku ICollectionView listy. Pozwala to na pisanie logiki, która może zwracać wartość logiczną określającą, czy dany element powinien być zawarte w ostatecznym widoku. Logika może być bardzo prosta (wystarczy zwrócić wartość logiczną obiektu) lub bardzo złożona, wszystko zależy od Ciebie.

 40
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-10 18:54:00

Poniższy kod może pomóc ci zrozumieć rzeczywiste użycie predykatów (w połączeniu z nazwanymi iteratorami).

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;
        }
    }
}
 14
Author: Brahim Boulkriat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-03 11:51:56

W C# predykaty są po prostu delegatami zwracającymi wartości logiczne. Są przydatne (z mojego doświadczenia), gdy przeszukujesz kolekcję przedmiotów i chcesz czegoś konkretnego.

Ostatnio natknąłem się na nie w użyciu kontrolek stron trzecich (takich jak treeviews), więc kiedy muszę znaleźć węzeł w drzewie, używam .Metoda Find() i podaj predykat, który zwróci konkretny węzeł, którego szukam. W twoim przykładzie, jeśli 'a' mod 2 jest równe 0, delegat zwróci true. Przyznane, gdy Szukam węzła w widoku drzewa, porównuję jego nazwę, tekst i właściwości wartości dla dopasowania. Kiedy delegat znajdzie dopasowanie, zwraca konkretny węzeł, którego szukałem.

 12
Author: osij2is,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-10 19:00:07