いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Linq入門記-18 (LINQ To Object, 拡張メソッド解決, 拡張メソッド, Extension Method)


今回は、拡張メソッド解決について記述します。
本来であれば、変換演算子の「AsEnumerableメソッド」について
記述するところなのですが、AsEnumerableメソッドの主な利用方法が
この拡張メソッド解決に絡んできますので、先にこちらを説明しておこうと思いました。


LINQにおける、拡張メソッド解決とは

クエリ演算子と同じ書式の拡張メソッドを定義して、そちらを呼ぶようにさせること。

と覚えておくといい感じです。


実際に例を見た方がわかりやすいと思います。


以下のようなクラスを定義したとします。

    public class Person
    {
        public int    Id   { get; set; }
        public string Name { get; set; }
    }
    
    public class Persons : List<Person>
    {
    }

ここのデータを表すPersonクラス。各Personのシーケンスを表すPersonsクラスです。


以下のクエリを発行したとします。

var persons = new Persons();
persons.Add(...);

var query = from aPerson in persons
            where ...
            select aPerson;
            
foreach (var aPerson in query)
{
    ....
}


実行時には、クエリは拡張メソッドの呼び出しに変更されますので

var query = persons.Where(...).Select(aPerson => aPerson);

となります。
上記のクエリにて、whereを利用していますが
このとき呼ばれるのは、当然IEnumerable.Where拡張メソッドです。


拡張メソッド解決を行うには、以下のようにPersonsクラスのWhere拡張メソッドを定義します。

    public static class PersonExtension
    {
        public static Persons Where(this Persons self, Func<Person, bool> predicate)
        {
            var result = new Persons();
            
            Console.WriteLine("========= WHERE ========");
            foreach (var aPerson in self)
            {
                if (predicate(aPerson))
                {
                    result.Add(aPerson);
                }
            }
            
            return result;
        }
    }


上記の拡張メソッドを定義した上で、再度クエリを発行すると
今度は、IEnumerable.Whereではなく、PersonExtension.Whereが
呼ばれます。

var query = from aPerson in persons
            where ...
            select aPerson;
            
foreach (var aPerson in query)
{
    ....
}


今度は、以下のように出力されます。

========= WHERE ========
....
....


同じ要領で、他のクエリ言語を拡張メソッド解決を利用して処理を行う事は
あまり無いもしれませんが、知っておくと役に立ちます。