Использование LINQ с классами, реализующими неуниверсальный интерфейс ICollection.
-
11-09-2019 - |
Вопрос
Я хотел запустить запрос LINQ к MatchCollection
объект, но обнаружил, что это невозможно, поскольку он не реализует ICollection<T>
, только ICollection
.
Каков наилучший вариант использования LINQ с неуниверсальными коллекциями как с точки зрения краткости кода, так и с точки зрения производительности и использования памяти?
(Если интересно, вот код, отличный от LINQuified:)
MatchCollection fieldValues = Regex.Matches(fieldValue, @"(?<id>\d+);#(?<text>[^;|^$]+)");
foreach (Match m in fieldValues)
{
if (m.Groups["text"].Value.Equals(someString))
{
// Do stuff
}
}
Решение
Вы можете включить свой 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>()
вместо.
Другие советы
Попробуйте использовать метод расширения 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;