C#のLINQの関数であるAsEnumerable()
の使い方についてです。
IEnumerable
を継承したクラスがLINQの関数を隠してしまったときに使うことが出来ます。
この記事には.NET Framework 4.6.1を使用しています。
LINQの関数と同じ名前の関数を作ってしまったとき
LINQの関数群は便利ですよね。
配列やリストに対していろいろなことが出来ます。
さて今回、私はこんなスペシャルなリストクラスを作ってみました。
Program.cs
// 既存のリストを遥かに超えた性能を持つスペシャルなリストクラス private class SpecialList<T> : List<T> { // スペシャルなため既存の考えにとらわれない! // 常時"false"を返すAny()関数を所持しているのだ! public bool Any() { return false; } }
どこらへんがスペシャルなのかはさておき、問題はこのクラスが持っている関数です。
Any()
という関数を所持しています。
LINQにも同名の関数があります。
この場合、Any()
を呼ぶとどうなってしまうのでしょうか。
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { // 既存のリストを遥かに超えた性能を持つスペシャルなリストクラス private class SpecialList<T> : List<T> { // スペシャルなため既存の考えにとらわれない! // 常時"false"を返すAny()関数を所持しているのだ! public bool Any() { return false; } } static void Main( string[] args ) { // 名前データ SpecialList<int> numbers = new SpecialList<int>() { 1, 2, 3 }; // スペシャルなAny() bool isAny = numbers.Any(); // 結果発表 System.Console.WriteLine( "numbers:{0}", numbers.Text() ); System.Console.WriteLine( "any :{0}", isAny ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
numbers:[1], [2], [3],
any :False
False
が返ってきました。
LINQのAny()
が呼ばれたのなら、True
が返ってくるはずです。
どうやらスペシャルなリストのAny()
の方が呼ばれたようです。
ではこのスペシャルなリストはLINQのAny()
を呼ぶことはできないのでしょうか。
こういう場合は、AsEnumerable()
という関数があります。
public static IEnumerable<TSource> AsEnumerable<TSource>( this IEnumerable<TSource> source );
Enumerable.AsEnumerable(TSource) メソッド (IEnumerable(TSource)) (System.Linq)
これを使えばIEnumerable
型が返ってきます。
これに対してLINQの関数を呼べば、隠蔽された関数も呼べるようになります。
Program.cs
using System.Linq; using System.Collections; using System.Collections.Generic; public static class Program { // 既存のリストを遥かに超えた性能を持つスペシャルなリストクラス private class SpecialList<T> : List<T> { // スペシャルなため既存の考えにとらわれない! // 常時"false"を返すAny()関数を所持しているのだ! public bool Any() { return false; } } static void Main( string[] args ) { // 名前データ SpecialList<int> numbers = new SpecialList<int>() { 1, 2, 3 }; // スペシャルなAny() bool isAny = numbers.Any(); bool isAnyLinq = numbers.AsEnumerable().Any(); // 結果発表 System.Console.WriteLine( "numbers:{0}", numbers.Text() ); System.Console.WriteLine( "any :{0}", isAny ); System.Console.WriteLine( "anyLINQ:{0}", isAnyLinq ); // 入力待ち用 System.Console.ReadKey(); } /// <summary> /// 簡易的なシーケンスのテキスト取得処理 /// </summary> public static string Text( this IEnumerable i_source ) { string text = string.Empty; foreach( var value in i_source ) { text += string.Format( "[{0}], ", value ); } return text; } } // class Program
numbers:[1], [2], [3],
any :False
anyLINQ:True
もしスペシャルなリストを使ってLINQの関数を呼ぶときは、AsEnumerable()
を七兆回ほど呼んでみてください。
LINQのリンク
- LINQ一覧
www.urablog.xyz