I recently came across a peculiar issue when using the Regex type “MatchCollection” in .NET Core. Or to be more specific, in a .NET Standard library. And while the fix was simple, it actually was an interesting insight into .NET Core vs .NET Framework, and how the mini-fragmentation we have going on between the two frameworks is hard to document.

First let’s rewind. I started off writing code that was pretty similar to the following :

Regex.Matches(stringText, @"myRegex").Select(x => x.value);

When I wrote this code, I had written it inside a .NET Core project. Pretty simple and for the most part, the Regex part looks exactly the same as it did in .NET Framework. However I then had a need to move this code into a library to be shared across two different projects. Naturally I made the library .NET Standard and suddenly I got the following error.

‘MatchCollection’ does not contain a definition for ‘Select’ and no accessible extension method ‘Select’ accepting a first argument of type ‘MatchCollection’ could be found

Interesting. Same code, different platform (.NET Core vs .NET Standard), and suddenly our innocuous “framework” looking code doesn’t work. What gives?

Well, Here’s the definition of MatchCollection in .NET Core

public class MatchCollection : IList<Match>, IReadOnlyList<Match>, IList

And here’s the definition in .NET Framework.

public class MatchCollection : ICollection

So the .NET Core implementation actually implements more interfaces than that of .NET Framework. Infact because it implements IList<T>, it actually implements IEnumerable<T>. “Select”, is a LINQ method that works with IEnumerable<T>, but not ICollection. So using this in .NET Framework will not work.

But I’m using .NET Standard you say! That’s true but remember, .NET Standard enforces a “minimum” implementation – much like an interface would enforce a minimum requirement on a class. But it doesn’t mean that class can’t go over and beyond. As it so happens, the .NET Standard definition of MatchCollection only requires the implementation of ICollection, but it does not require IEnumerable<T> to be implemented. So you cannot use LINQ methods on a Regex MatchCollection if you are targeting anything other then .NET Core.

I kind of lived with this since it wasn’t such a big deal. But given I couldn’t use IEnumerable<T> methods on my MatchCollection anymore, I headed to the Microsoft Documentation for a couple of examples of how my could should work.

And here’s the actual issue.

The documentation *does not* show the differences between .NET Core and .NET Framework. The .NET Core 3.1 documentation for MatchCollection is found here : https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.matchcollection?view=netcore-3.1

Note that it’s definition as per that documentation is :

public class MatchCollection : ICollection

That is wrong!

As it turns out, in 2018, this issue was raised here : https://github.com/dotnet/docs/issues/5608 which if you follow the trail of tickets, leads you to this ticket : https://github.com/MicrosoftDocs/feedback/issues/226. And right there slapped on the bottom.

Welp. Spamming Autocomplete options instead of reading documentation it is!