Predicate Delegates in C #

256

Czy możesz mi wyjaśnić:

  • Co to jest delegat predykatu?
  • Gdzie powinniśmy stosować predykaty?
  • Jakieś najlepsze praktyki korzystania z predykatów?

Doceniamy opisowy kod źródłowy.

Canavar
źródło

Odpowiedzi:

319

Predykat to funkcja zwracająca truelub false. Delegat predykatu jest odniesieniem do predykatu.

Tak więc w zasadzie delegat predykatu jest odwołaniem do funkcji, która zwraca truelub false. Predykaty są bardzo przydatne do filtrowania listy wartości - oto przykład.

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int> { 1, 2, 3 };

        Predicate<int> predicate = new Predicate<int>(greaterThanTwo);

        List<int> newList = list.FindAll(predicate);
    }

    static bool greaterThanTwo(int arg)
    {
        return arg > 2;
    }
}

Teraz, jeśli używasz C # 3, możesz użyć lambda do reprezentowania predykatu w czystszy sposób:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int> { 1, 2, 3 };

        List<int> newList = list.FindAll(i => i > 2);
    }
}
Andrew Hare
źródło
@Andrew Hare: w swoim pierwszym fragmencie kodu powinno to być yeild returnzamiast tego? Lub jak to działa, jak iteruje się po całej liście?
VoodooChild,
5
@VoodooChild: Pamiętaj, że orzeczenie zostanie wywołana dla każdego elementu w sekwencji po kolei . Tak greaterThanTwosię returnnie stało, yield returnponieważ jest to FindAllmetoda, która obsługuje sekwencję za Ciebie.
Andrew Hare,
1
@AndrewHare, czy możliwe jest, aby i > valzamiast tego i > 2, gdzie valwartość jest wprowadzana przez użytkownika.
Mourya,
81

Przechodząc od odpowiedzi Andrzeja w odniesieniu do c # 2 i c # 3 ... możesz także zrobić je w linii dla jednorazowej funkcji wyszukiwania (patrz poniżej).

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> list = new List<int> { 1, 2, 3 };

        List<int> newList = list.FindAll(delegate(int arg)
                           {
                               return arg> 2;
                           });
    }
}

Mam nadzieję że to pomoże.

WestDiscGolf
źródło
11

Po prostu delegat, który zwraca wartość logiczną. Jest często używany na listach filtrujących, ale można go używać gdziekolwiek chcesz.

List<DateRangeClass>  myList = new List<DateRangeClass<GetSomeDateRangeArrayToPopulate);
myList.FindAll(x => (x.StartTime <= minDateToReturn && x.EndTime >= maxDateToReturn):
Adam Carr
źródło
9

Jest to dobry artykuł na orzeczników tutaj , choć to z czasów .NET2, więc tam nie ma wzmianki o wyrażeniach lambda tam.

Łukasz
źródło
Link w Twojej odpowiedzi nie prowadzi już do faktycznego artykułu
David Cram
@David Cram: Dzięki, zaktualizowałem link do korzystania z Wayback Machine, chociaż artykuł wygląda na bardzo stary.
Łukasza
6

Co to jest Predicate Delegate?

1) Predicate to funkcja zwracająca wartość true lub false. Ta koncepcja pojawiła się w .NET 2.0. 2) Jest używany z wyrażeniem lambda (=>). Jako argument przyjmuje typ ogólny. 3) Umożliwia zdefiniowanie funkcji predykatu i przekazanie jej jako parametru do innej funkcji. 4) Jest to szczególny przypadek a Func, ponieważ wymaga tylko jednego parametru i zawsze zwraca wartość bool.

W przestrzeni nazw C #:

namespace System
{   
    public delegate bool Predicate<in T>(T obj);
}

Jest zdefiniowany w przestrzeni nazw Systemu.

Gdzie powinniśmy skorzystać z Predicate Delegate?

Powinniśmy użyć Predicate Delegate w następujących przypadkach:

1) Do wyszukiwania przedmiotów w ogólnej kolekcji. na przykład

var employeeDetails = employees.Where(o=>o.employeeId == 1237).FirstOrDefault();

2) Podstawowy przykład, który skraca kod i zwraca true lub false:

Predicate<int> isValueOne = x => x == 1;

teraz zadzwoń powyżej predykatu:

Console.WriteLine(isValueOne.Invoke(1)); // -- returns true.

3) Anonimową metodę można również przypisać do typu delegata predykatu, jak poniżej:

Predicate<string> isUpper = delegate(string s) { return s.Equals(s.ToUpper());};
    bool result = isUpper("Hello Chap!!");

Jakieś najlepsze praktyki dotyczące predykatów?

Używaj Func, wyrażeń lambda i delegatów zamiast predykatów.

Gul Md Ershad
źródło
5

Metody wyszukiwania oparte na predykatach pozwalają delegatowi metody lub wyrażeniu lambda zdecydować, czy dany element jest „dopasowany”. Predykat to po prostu delegat akceptujący obiekt i zwracający wartość true lub false: public delegate bool Predicate (obiekt T);

   static void Main()
        {
            string[] names = { "Lukasz", "Darek", "Milosz" };
            string match1 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
            //or
            string match2 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
            //or
            string match3 = Array.Find(names, x => x.Contains("L"));


            Console.WriteLine(match1 + " " + match2 + " " + match3);     // Lukasz Lukasz Lukasz
        }
        static bool ContainsL(string name) { return name.Contains("L"); }
lukaszk
źródło
2

Jeśli korzystasz z VB 9 (VS2008), predykat może być złożoną funkcją:

Dim list As New List(Of Integer)(New Integer() {1, 2, 3})
Dim newList = list.FindAll(AddressOf GreaterThanTwo)
...
Function GreaterThanTwo(ByVal item As Integer) As Boolean
    'do some work'
    Return item > 2
End Function

Możesz też napisać orzeczenie jako lambda, o ile jest to tylko jedno wyrażenie:

Dim list As New List(Of Integer)(New Integer() {1, 2, 3})
Dim newList = list.FindAll(Function(item) item > 2)
danlash
źródło
0

Predykat należy do kategorii ogólnych delegatów w języku C #. Jest to wywoływane z jednym argumentem i zawsze zwraca wartość logiczną. Zasadniczo predykat służy do testowania warunku - prawda / fałsz. Wiele klas obsługuje predykaty jako argument. Na przykład list.findall oczekuje predykatu parametru. Oto przykład predykatu.

Wyobraź sobie wskaźnik funkcji z podpisem -

bool delegate myDelegate (dopasowanie T);

Oto przykład

Node.cs

namespace PredicateExample
{
    class Node
    {
        public string Ip_Address { get; set; }
        public string Node_Name { get; set; }
        public uint Node_Area { get; set; }
    }
}

Główna klasa -

using System;
using System.Threading;
using System.Collections.Generic;

namespace PredicateExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Predicate<Node> backboneArea = Node =>  Node.Node_Area == 0 ;
            List<Node> Nodes = new List<Node>();
            Nodes.Add(new Node { Ip_Address = "1.1.1.1", Node_Area = 0, Node_Name = "Node1" });
            Nodes.Add(new Node { Ip_Address = "2.2.2.2", Node_Area = 1, Node_Name = "Node2" });
            Nodes.Add(new Node { Ip_Address = "3.3.3.3", Node_Area = 2, Node_Name = "Node3" });
            Nodes.Add(new Node { Ip_Address = "4.4.4.4", Node_Area = 0, Node_Name = "Node4" });
            Nodes.Add(new Node { Ip_Address = "5.5.5.5", Node_Area = 1, Node_Name = "Node5" });
            Nodes.Add(new Node { Ip_Address = "6.6.6.6", Node_Area = 0, Node_Name = "Node6" });
            Nodes.Add(new Node { Ip_Address = "7.7.7.7", Node_Area = 2, Node_Name = "Node7" });

            foreach( var item in Nodes.FindAll(backboneArea))
            {
                Console.WriteLine("Node Name " + item.Node_Name + " Node IP Address " + item.Ip_Address);
            }

            Console.ReadLine();
        }
    }
}
zręczny
źródło
0

Po prostu -> podają wartości Prawda / Fałsz w oparciu o warunki najczęściej używane w zapytaniach. używane głównie z delegatami

rozważ przykład listy

List<Program> blabla= new List<Program>();
        blabla.Add(new Program("shubham", 1));
        blabla.Add(new Program("google", 3));
        blabla.Add(new Program("world",5));
        blabla.Add(new Program("hello", 5));
        blabla.Add(new Program("bye", 2));

zawiera nazwiska i wiek. Teraz powiedzmy, że chcemy znaleźć nazwiska pod warunkiem Więc użyję,

    Predicate<Program> test = delegate (Program p) { return p.age > 3; };
        List<Program> matches = blabla.FindAll(test);
        Action<Program> print = Console.WriteLine;
        matches.ForEach(print);

próbowałem zachować prostotę!

Shubham Khare
źródło