web-dev-qa-db-ja.com

C#の述語とは何ですか?

私は述語を使用するのは非常に新しく、ちょうど書き方を学びました:

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

述部は何を返しますか?また、プログラミング時にどのように役立ちますか?

161
Jebli

Predicate<T>は、与えられたTオブジェクトに何かが当てはまるかどうかを基本的にテストする便利な方法を提供する機能的な構成体です。

たとえば、クラスがあるとします:

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

List<Person> peopleがあり、リストにOscarという名前の人がいるかどうかを知りたいとしましょう。

WithoutPredicate<Person>(またはLinq、またはその派手なもの)を使用して、次の操作を行うことで常にこれを達成できました。

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

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

これで問題ありませんが、「Ruth」という名前の人がいるかどうかを確認したいとしましょう。または、年齢が17歳の人ですか?

Predicate<Person>を使用すると、LOTが少ないコードを使用して次のことがわかります。

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

私はたくさんコードが少ないではなく、たくさん速いと言ったことに注意してください。開発者がよく持っている誤解は、何かが1行かかる場合、10行かかるものよりもパフォーマンスが優れている必要があるということです。しかし、舞台裏では、Predicate<T>をとるFindメソッドは、単に列挙するだけです。同じことは、Linqの多くの機能にも当てはまります。

それでは、質問の特定のコードを見てみましょう。

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

ここには、Predicate<int> preを取り、int aを返すa % 2 == 0があります。これは本質的に偶数のテストです。それが意味することは:

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

等々。これは、List<int> intsがあり、最初の偶数を見つけたい場合にも、これを行うことができることを意味します。

int firstEven = ints.Find(pre);

もちろん、コードで使用できる他の型と同様に、変数にわかりやすい名前を付けることをお勧めします。したがって、上記のpreevenFinderまたはisEvenのようなものに変更することをお勧めします。次に、上記のコードは非常に明確です。

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

述部は、定義により常にブール値を返します。

Predicate<T> は、基本的にFunc<T,bool>と同じです。

述語はプログラミングに非常に役立ちます。多くの場合、実行時にロジックを提供できるようにするために使用されます。ロジックは必要に応じて単純または複雑にすることができます。

たとえば、WPFはListViewのICollectionViewのフィルタリングの入力としてPredicate<T>を使用します。これにより、特定の要素を最終ビューに含めるかどうかを決定するブール値を返すロジックを作成できます。ロジックは非常に単純(オブジェクトにブール値を返す)にすることも、非常に複雑にすることもできます。

43
Reed Copsey

次のコードは、実際の述語の使用方法を理解するのに役立ちます(名前付きイテレーターと組み合わせて)。

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

C#では、述語はブール値を返す単なるデリゲートです。オブジェクトのコレクションを検索し、特定の何かが必要な場合、これらは便利です(私の経験では)。

私は最近、ツリービューなどのサードパーティのWebコントロールを使用してそれらに遭遇しました。そのため、ツリー内でノードを見つける必要がある場合、.Find()メソッドを使用して、特定のノードを返す述語を渡します探している。あなたの例では、「a」mod 2が0の場合、デリゲートはtrueを返します。確かに、ツリービューでノードを探しているときに、名前、テキスト、および値のプロパティを比較して一致させます。デリゲートは一致を見つけると、探していた特定のノードを返します。

14
osij2is