C#での述語デリゲート


256

説明していただけますか:

  • 述語デリゲートとは何ですか?
  • 述語はどこで使用すればよいですか?
  • 述語を使用する際のベストプラクティスはありますか?

記述的なソースコードは高く評価されます。

回答:


319

述語はtrueor を返す関数ですfalse。述語デリゲートは述語への参照です。

したがって、基本的に述語デリゲートはtrueor を返す関数への参照falseです。述語は、値のリストをフィルタリングするのに非常に役立ちます-以下に例を示します。

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

C#3を使用している場合は、ラムダを使用して述語をより簡潔に表すことができます。

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:最初のコードスニペットでは、yeild return代わりにする必要がありますか?または、それはどのように機能し、リスト全体をどのように繰り返しますか?
VoodooChild

5
@VoodooChild:述語はシーケンス内の各要素に対して順番呼び出されることに注意してください。だから、greaterThanTwo持っていreturnないyield returnことがあるので、FindAllあなたのためのシーケンスを処理している方法。
Andrew Hare

1
@AndrewHareはi > val、の代わりに i > 2valユーザーが入力した値を持つことができますか?
Mourya 2013年

81

Andrewのc#2とc#3に関する回答から先に進んでください。1回限りの検索機能のためにインラインで行うこともできます(以下を参照)。

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

お役に立てれば。


11

ブール値を返す単なるデリゲート。リストのフィルタリングによく使用されますが、どこでも使用できます。

List<DateRangeClass>  myList = new List<DateRangeClass<GetSomeDateRangeArrayToPopulate);
myList.FindAll(x => (x.StartTime <= minDateToReturn && x.EndTime >= maxDateToReturn):

9

.NET2時代のものですがここに述語に関する優れた記事があります。そのため、ラムダ式についての言及はありません。


回答のリンクが実際の記事にリンクしなくなった
David Cram

@デビッドクラム:記事を募集していますが、おかげで、私は、ウェイバックマシンを使用するためのリンクを更新しました本当に、今日の日付。
LukeH 2017年

6

述語デリゲートとは何ですか?

1)述語はtrueまたはfalseを返す機能です。この概念は.net 2.0フレームワークに組み込まれています。2)ラムダ式(=>)で使用されている。引数としてジェネリック型を取ります。3)述語関数を定義し、パラメーターとして別の関数に渡すことができます。4)これはの特殊なケースでありFunc、単一のパラメーターのみを受け取り、常にブール値を返します。

C#名前空間では:

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

これは、システム名前空間で定義されています。

述語デリゲートはどこで使用すればよいですか?

次の場合には、述語デリゲートを使用する必要があります。

1)一般的なコレクションのアイテムを検索するため。例えば

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

2)コードを短くしてtrueまたはfalseを返す基本的な例:

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

今、上記の述語を呼び出します:

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

3)以下のように、匿名メソッドを述語デリゲートタイプに割り当てることもできます。

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

述語に関するベストプラクティスはありますか?

述語の代わりにFunc、ラムダ式、デリゲートを使用します。


5

述語ベースの検索メソッドを使用すると、メソッドのデリゲートまたはラムダ式で、特定の要素が「一致」するかどうかを判断できます。述語は、単にオブジェクトを受け入れ、trueまたはfalseを返すデリゲートです。public delegate bool Predicate(T object);

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

2

VB 9(VS2008)を使用している場合、述語は複雑な関数になる可能性があります。

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

または、式が1つだけであれば、述語をラムダとして記述することもできます。

Dim list As New List(Of Integer)(New Integer() {1, 2, 3})
Dim newList = list.FindAll(Function(item) item > 2)

0

述語は、C#の一般的なデリゲートのカテゴリに分類されます。これは1つの引数で呼び出され、常にブール型を返します。基本的に、述語は条件をテストするために使用されます-true / false。多くのクラスは、述語を引数としてサポートしています。たとえば、list.findallはパラメータ述語を想定しています。以下は述語の例です。

シグネチャを持つ関数ポインタを想像してください-

boolデリゲートmyDelegate(Tマッチ);

ここに例があります

Node.cs

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

メインクラス-

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

0

単に->それらは主にクエリに使用される条件に基づいてTrue / False値を提供します。主にデリゲートで使用されます

リストの例を検討

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

名前と年齢が含まれています。ここで、条件に基づいて名前を検索したいとしましょう。

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

シンプルにしようとしました!


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.