views:

1145

answers:

2

I wanted to run a LINQ query against a MatchCollection object but found this wasn't possible as it doesn't implement ICollection<T>, just ICollection.

What is the best option for using LINQ with non-generic collections, both in terms of code conciseness but also performance and memory usage?

(If interested, here is the non-LINQuified code:)

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

Try to use the Cast extension method which will return an IEnumerable.

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

And event if you don't use the Cast method the compiler will infer the type of "query" to IEnumerable.

  var query = from Match v in fieldValues
                        select v;
Marwan Aouida
+3  A: 

You can include your someString filter with LINQ as well.

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
}

Note that the compiler translates a query like this...

var q = from MyType x in myEnum select x;

...into this...

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

...so including both the type and Cast<T>() is redundant.

Performance-wise, Cast<T>() just does an explicit type cast and yields the value, so the performance hit will be negligible. For legacy collections where you're not sure all members are of the desired type, you can use OfType<T>() instead.

dahlbyk
For some reason I didn't think this would work as MatchCollection isn't generic. Guess I should have tried it! Your explanation of the compiler translation was very helpful.
Alex Angas