Использование LINQ с классами, реализующими не общие ICollection

Я хотел запустить запрос LINQ для объекта MatchCollection, но обнаружил, что это невозможно, поскольку оно не реализует ICollection<T>, просто ICollection.

Каков наилучший вариант использования LINQ с не-генерическими коллекциями, как с точки зрения краткости кода, так и с точки зрения производительности и памяти?

(Если это интересно, вот код, не связанный с LINQuated:)

MatchCollection fieldValues = Regex.Matches(fieldValue, @"(?<id>\d+);#(?<text>[^;|^$]+)");
foreach (Match m in fieldValues)
{
    if (m.Groups["text"].Value.Equals(someString))
    {
        // Do stuff
    }
}

Ответ 1

Вы можете включить ваш фильтр someString с помощью LINQ.

var matches = Regex.Matches(fieldValue, @"(?<id>\d+);#(?<text>[^;|^$]+)");
var textMatches = from Match m in matches
                  where m.Groups["text"].Value.Equals(someString)
                  select m;

foreach (Match m in textMatches)
{
    // Do stuff
}

Обратите внимание, что компилятор переводит запрос следующим образом:

var q = from MyType x in myEnum select x;

... в это...

var q = from x in myEnum.Cast<MyType>() select x;

... поэтому включение типа и Cast<T>() является избыточным.

Производительность, Cast<T>() просто делает явный тип приведения и дает значение, поэтому удар производительности будет незначительным. Для устаревших коллекций, где вы не уверены, что все члены имеют нужный тип, вы можете вместо этого использовать OfType<T>().

Ответ 2

Попробуйте использовать метод расширения Cast, который вернет IEnumerable.

IEnumerable<Match> query = from Match m in fieldValues.Cast<Match>()
                           select m;

И если вы не используете метод Cast, компилятор выведет тип "запроса" на IEnumerable.

  var query = from Match v in fieldValues
                        select v;