foreach循环中的正则表达式MatchCollection [英] Regex MatchCollection in foreach loop

查看:217
本文介绍了foreach循环中的正则表达式MatchCollection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在对某些正则表达式进行快速控制台应用测试,并注意到一些奇怪的事情。我在一个字符串中抓取了一个MatchCollection标记,并在foreach循环中迭代它以打印出每个标记。这按预期工作。奇怪的是,当我试图访问
时,"群组"循环中每个Match对象的属性......它们被视为"对象",而不是"匹配"。很明显,打印只是按预期工作,因为对象的ToString方法打印出每个
匹配。但是,通常foreach循环可以告诉循环变量来自它正在运行的集合。为什么这不适用于MatchCollection? 

I was doing a quick console app test on some Regex, and noticed something odd. I grabbed a MatchCollection of tokens within a string, and iterated over that in a foreach loop to print each out. This worked as expected. The odd part was when I tried to access the "Groups" property of each Match object in the loop... they were being seen as "object", instead of "Match". It was obvious that the printing had worked as expected only because the ToString method of object printed out each Match. However, usually the foreach loop can tell what the loop variable will be from the collection it's operating on. Why doesn't this work with a MatchCollection? 

// Why doesn't this work?
foreach (var m in matches)
{
    foreach (var g in m.Groups)
    {
        Console.WriteLine(g);
    }
}

// Have to explicitly state what the loop variable is.
foreach (Match m in matches)
{
    foreach (Group g in m.Groups)
    {
        Console.WriteLine(g);
    }
}


无论如何,我只是好奇为什么'var'不能像我期望的那样工作。 

Anyway, I was just curious why 'var' doesn't work as I expect in this scenario. 

推荐答案

MatchCollection
实现
ICollection
。 ICollection实现了
IEnumerable
。 IEnumerable是非泛型枚举接口。它返回的所有内容都是object,因为这是唯一适用于非泛型的类型。因此,当foreach循环看到IEnumerable时,它将元素键入为对象。
.NET中的每个集合都以这种方式工作,如果它们在实现泛型时早于2.0。改变类型的层次结构正在发生变化,并且可能是一个突破性的变化来调整接口,尽管添加新的接口通常是有效的。尽管如此,绝大多数
2.0之前的版本都没有更新,因此您无法获得通用支持。这包括所有Winforms,核心类型和Regex。

MatchCollection implements ICollection. ICollection implements IEnumerable. IEnumerable is the non-generic enumeration interface. Everything it returns is object because that is the only type that works with non-generics. So when the foreach loop sees IEnumerable it types the elements as object. Every collection in .NET works this way if they pre-date 2.0 when generics were implemented. It is breaking change to change the hierarchy of a type and may be a breaking change to adjust the interfaces although adding new ones generally work. Nevertheless the vast majority of pre-2.0 collections weren't updated so you don't get generic support. This includes all of Winforms, the core types and Regex.

使用非通用IEnumerable时的正确解决方案是使用OfType< T>。扩展方法。

The correct solution when working with a non-generic IEnumerable is to use the OfType<T> extension method.

//These are objects because matches is IEnumerable
foreach (var m in matches)
{
}

//Solution 1 - be explicit
foreach (Match m in matches)
{}

//Solution 2 - extension method
foreach (var m in matches.OfType<Match>())
{}

解决方案1有效,因为您正在枚举对象和运行时为每个项目进行匹配的类型转换。如果这些项目中的任何一个失败,那么它就会崩溃。

Solution 1 works because you're enumerating object and the runtime does a typecast to Match for each item. If any of those items fails then it crashes.

解决方案2对我来说是更清洁的选择。首先,你回到使用var。其次OfType< T>对每个值进行运行时检查。如果失败则会跳过它,这样你就不会崩溃。 OfType< T>获取IEnumerable并返回IEnumerable< T>
这是允许编译器知道返回的项目的原因。

Solution 2 is the cleaner option to me. Firstly you are back to using var. Secondly OfType<T> does a runtime check of each value. If it fails then it skips over it so you won't crash. OfType<T> takes IEnumerable and returns IEnumerable<T> which is what allows the compiler to know what items are being returned.

在某些情况下,已经提供了扩展方法。例如,ADO.NET具有扩展方法的整个命名空间,用于将(预)通用集合转换为IEnumerable< T>。所以它们可以在没有明确类型的情况下使用。

In some cases there are already extension methods provided. ADO.NET, for example, has an entire namespace of extension methods to convert (pre) generic collections to IEnumerable<T> so they can be used without an explicit type.


这篇关于foreach循环中的正则表达式MatchCollection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆