问题描述:

I was writing this piece of C# code:

static void Main()

{

List<string> matches = new List<string>();

var result = Regex.Matches(myString, @"\((.*?)\)");

foreach(var x in result)

matches.Add(x.Groups[1].Value.ToString());

}

and I was surprised to see it fail with this error message:

Type 'object' does not contain a definition for 'Groups' and no

extension method 'Groups' of type 'object' could be found.

However, this works:

foreach(Match x in result)

matches.Add(x.Groups[1].Value.ToString());

The Matches() method returns a MatchCollection, shouldn't it be clear that x is a Match?

网友答案:

shouldn't it be clear that x is a Match?

Sadly no.

MatchCollection implements IEnumerable, the non-generic legacy interface. It does not implement IEnumerable<Match>. So no, that is not clear.

Because the foreach loop was designed in an era before generics, it automatically inserts a cast to the loop variable type. That is

foreach(Match x in result)
  matches.Add(x.Groups[1].Value.ToString());

is the moral equivalent of

IEnumerator enumtor = result.GetEnumerator();
while (enumtor.MoveNext())
{
    Match x = (Match)(enumtor.Current);
    ...

You could have said

foreach(Giraffe x in result)

and it would have compiled just fine, and died at runtime.

When you say

foreach(var x in result)

The compiler sees that there is no type information to infer beyond object, so that's what it gives you for the type of x. Your error then follows from there.

I do not know why the collection has not been updated to make it more amenable to static typing; you'd have to ask the BCL team.

相关阅读:
Top