Using LINQ with classes implementing non-generic I

2019-04-20 11:49发布

问题:

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:

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.



回答2:

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;