私は述語の使用に非常に慣れておらず、書き方を学びました。
Predicate<int> pre = delegate(int a){ a %2 == 0 };
述語は何を返しますか、そしてプログラミング時にどのように役立ちますか?
Predicate<T>
T
は、特定のオブジェクトが真であるかどうかを基本的にテストする便利な方法を提供する関数構造です。
たとえば、次のクラスがあるとします。
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
ここList<Person> people
で、リストに Oscar という名前の人がいるかどうかを知りたいとします。
Predicate<Person>
(またはLinq、またはその手の込んだもの)を使用しなくても、次のことを行うことでいつでもこれを達成できます。
Person oscar = null;
foreach (Person person in people) {
if (person.Name == "Oscar") {
oscar = person;
break;
}
}
if (oscar != null) {
// Oscar exists!
}
これでいいのですが、「ルース」という名前の人がいるかどうかを確認したいとしましょう。それとも17歳の人?
を使用するPredicate<Person>
と、多くの少ないコードを使用してこれらのものを見つけることができます。
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 行で済むものよりも優れたパフォーマンスを発揮するはずだというものです。しかし、舞台裏では、 を受け取るメソッドは、結局のところ単に列挙しているだけです。Linq の多くの機能についても同じことが言えます。Find
Predicate<T>
それでは、質問の特定のコードを見てみましょう。
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);
もちろん、コードで使用できる他の型と同様に、変数にわかりやすい名前を付けることをお勧めします。pre
したがって、上記をまたはのようなものに変更することをお勧めしますevenFinder
-isEven
それらの線に沿ったもの。次に、上記のコードはより明確になります。
int firstEven = ints.Find(evenFinder);
Predicate は、定義上、常にブール値を返します。
Predicate<T>
と基本的に同じですFunc<T,bool>
。
述語は、プログラミングで非常に役立ちます。多くの場合、必要に応じて単純または複雑なロジックを実行時に提供できるようにするために使用されます。
たとえば、WPF はPredicate<T>
ListView の ICollectionView のフィルタリングの入力として を使用します。これにより、特定の要素を最終ビューに含める必要があるかどうかを決定するブール値を返すロジックを記述できます。ロジックは非常に単純 (オブジェクトに対してブール値を返すだけ) にすることも、非常に複雑にすることもできます。
次のコードは、述語の実際の使用法を理解するのに役立ちます (名前付き反復子と組み合わせて)。
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;
}
}
}
C# では、述語は単にブール値を返すデリゲートです。これらは、(私の経験では) オブジェクトのコレクションを検索していて、特定の何かが必要な場合に役立ちます。
最近、サードパーティの Web コントロール (ツリービューなど) を使用してそれらに遭遇したので、ツリー内のノードを見つける必要がある場合は、.Find() メソッドを使用して、特定のノードを返す述語を渡します。探している。あなたの例では、「a」mod 2 が 0 の場合、デリゲートは true を返します。確かに、ツリービューでノードを探しているときは、その名前、テキスト、および値のプロパティを比較して一致するものを探します。デリゲートが一致を見つけると、探していた特定のノードを返します。