MatchCollection・GroupCollection・CaptureCollectionの各コレクションは、当初非ジェネリックなIEnumerableインターフェイスのみを実装する型指定されていないコレクションとして登場し、その後.NET Standard 2.1/.NET Core 2.0にてIEnumerable<T>/ICollection<T>/IList<T>を実装するようになり、型指定されたコレクションとして扱うことができるようになっています。
一方、Match/Group/CaptureCollectionのGetEnumeratorメソッドは、おそらくAPI互換性維持の観点から、IEnumerable<T>の実装以降も非ジェネリックなIEnumeratorを返す実装のままとなっています。 このためC#では、これらのコレクションクラスから取得した列挙子IEnumeratorで列挙する場合、var
による暗黙的な型指定を行うとobject
として列挙されます。
using System;
using System.Text.RegularExpressions;
class Sample {
static void PrintMatches(MatchCollection matches)
{
// MatchCollectionでは非ジェネリックなIEnumeratorを返すため、
// 列挙する際に暗黙的な型指定を行うと、objectとして扱われる
foreach (/*Match*/ var match in matches) {
// matchの型はobjectとして扱われるため、Valueプロパティを参照できない
Console.WriteLine(match.Value); // error CS1061: 'object' に 'Value' の定義が含まれておらず、型 'object' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Value' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。
PrintGroups(match.Groups); // error CS1061: 'object' に 'Groups' の定義が含まれておらず、型 'object' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Groups' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。
}
}
static void PrintGroups(GroupCollection groups)
{
// GroupCollectionの場合もMatchCollectionと同様
foreach (/*Group*/ var group in groups) {
Console.WriteLine(group.Value); // error CS1061: 'object' に 'Value' の定義が含まれておらず、型 'object' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Value' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。
PrintCaptures(group.Captures); // error CS1061: 'object' に 'Captures' の定義が含まれておらず、型 'object' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Captures' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。
}
}
static void PrintCaptures(CaptureCollection captures)
{
// CaptureCollectionの場合もMatchCollectionと同様
foreach (/*Capture*/ var capture in captures) {
Console.WriteLine(capture.Value); // error CS1061: 'object' に 'Value' の定義が含まれておらず、型 'object' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Value' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。
}
}
static void Main()
{
PrintMatches(Regex.Matches("text", "pattern"));
}
}
したがって、これらのコレクションをforeachで列挙を行う際には、明示的に型指定する、IEnumerable<Match>等にキャストしてから列挙する、LINQのOfType<Match>()メソッド・Cast<Match>()メソッドを用いて型変換してから列挙する、などする必要があります。
Match/Group/CaptureCollectionから直接ではなく、ジェネリックインターフェイスを介してGetEnumeratorメソッドを呼び出す場合は、ジェネリックな(型指定された)列挙子IEnumerator<T>を取得できます。 そのため、これらのコレクションを引数としてとる場合は、Match/Group/CaptureCollectionの代わりにIEnumerable/IReadOnlyCollection/IReadOnlyList<Match/Group/Capture>などで受けるようにすることもできます。
IEnumerable・IEnumeratorインターフェイスと列挙について詳しくはIEnumerable・IEnumeratorを参照してください。