前回、クエリ可能となるオブジェクトは
IEnumerable
をサポートしているオブジェクトであると書きましたが
ArrayListや昔のコレクションクラスなどは
IEnumerable
というジェネリックでない方のインターフェースを実装しています。
その場合、前回と同じように
IList list = new ArrayList(); list.AddRange(new object[]{"hoge", "hehe", "fuga"}); var query = from str in list where str.StartsWith("h") select str
と書くと、以下のようなエラーがでます。
LinqSample.cs(49,30): error CS1934: ソース型 'System.Collections.IList' のクエリ パターンの実装が見つかりませんでした。'Select' が見つかりません。範囲変数 'str' の型を明示的に指定してください。
つまり、内部の型が分からないから明示的に指定しろって言われます。
そこで以下のように書くとうまくいきます。
IList list = new ArrayList(); list.AddRange(new object[]{"hoge", "hehe", "fuga"}); var query = from string str in list where str.StartsWith("h") select str
from句のループ変数に明示的に型を指定します。
で、以下サンプルです。
// vim:set ts=4 sw=4 et ws is nowrap ft=cs: using System; using System.Linq; namespace Gsf.Samples.Tmp{ class LinqSample1{ static void Main(){ IList list = new List(new []{"hoge", "hehe", "fuga"}); List list2 = list as List ; // // ERROR. // // LinqSample.cs(49,30): error CS1934: ソース型 'System.Collections.IList' のクエリ // パターンの実装が見つかりませんでした。'Select' // が見つかりません。範囲変数 'elem' の型を明示的に指定してください。 // //var query = // from elem in list // select elem; var query = from string elem in list select elem; foreach(string s in query){ Console.WriteLine(s); } // // Linqはクエリ可能なオブジェクトかどうかを // 実際のオブジェクトが格納されている変数の型で // 判断します。なので、この場合list2はジェネリック // リストの変数に格納しているので明示的な型宣言は // いりません。 // query = from elem in list2 select elem; foreach(string s in query){ Console.WriteLine(s); } } } }