При перечислении MatchCollection, почему var приводит к типу объекта, а не к типу соответствия?

Я заметил что-то, что кажется странным в следующем коде:

MatchCollection mc = Regex.Matches(myString, myPattern);
foreach(var match in mc)
    Console.WriteLine(match.Captures[0]); // <-- this line is invalid, unless I replace 'var' above with 'Match'

Переменная match имеет тип Object, а не match. Я использую перечисление коллекций с помощью var без каких-либо проблем. Почему MatchCollection отличается?

Ответ 1

MatchCollection был написан до .NET 2, поэтому он просто реализует IEnumerable, а не IEnumerable<T>. Однако вы можете использовать Cast, чтобы исправить это очень легко:

foreach(var match in mc.Cast<Match>())

Если вы даете переменной явный тип, например:

foreach(Match match in mc)

... тогда компилятор С# автоматически добавляет листинг для каждого элемента. Это было необходимо в С# 1, чтобы избежать использования всех ваших кодов.

(Логически даже при var там задействовано преобразование, но оно всегда от одного типа к одному и тому же типу, поэтому ничего не нужно испускать.) Подробнее см. в разделе 8.8.4 спецификации С# 4.

Ответ 2

Попробуйте следующее:

foreach(Match match in mc)

Поскольку MatchCollection не реализует IEnumerable<T>, счетчик в foreach получит object для каждого Match в последовательности. Это ваша задача, чтобы применить объект к нужному типу.

Поэтому, когда вы используете var в цикле foreach, вы неявно печатаете Match до object, так как это то, что дает перечислитель. Явным образом набрав Match to Match, вы даете указание компилятору отдать каждому соответствию нужный тип от вашего имени.

Ответ 3

Использование var не подходит в этом контексте.

http://msdn.microsoft.com/en-us/library/bb384061.aspx

"Однако использование var имеет, по крайней мере, потенциал, чтобы сделать ваш код более сложным для понимания для других разработчиков. По этой причине документация на С# обычно использует var только тогда, когда это необходимо."