При перечислении 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 только тогда, когда это необходимо."