Ответ 1
Это потому, что свойство GridView.Rows
возвращает тип GridViewRowCollection
.
В этом случае var
не может вывести из использования, что объект будет DataGridViewRow
внутри.
Источник: Свойство GridView.Rows
Я новичок в С# и задаю вопрос об использовании "var"
Когда я использую следующий код, все работает отлично
foreach(DataGridViewRow row in myGrid.Rows)
{
if (row.Cells[2].Value.ToString().Contains("51000"))
{
row.Cells[0].Value = "X";
}
}
Но когда я меняю DataGridViewRow
на var
, я получаю и ошибка, которая указывает
'object' не содержит определения для "Ячейки" и никакого расширения метод "Ячейки", принимающие первый аргумент типа "объект", может быть (вам не хватает директивы использования или ссылки на сборку?)
Это потому, что свойство GridView.Rows
возвращает тип GridViewRowCollection
.
В этом случае var
не может вывести из использования, что объект будет DataGridViewRow
внутри.
Источник: Свойство GridView.Rows
myGrid.Rows
имеет тип DataGridViewRowCollection
.
Эта вещь довольно старая, ее определение гласит:
public class DataGridViewRowCollection : ICollection, IEnumerable, IList
Вы видите не общие интерфейсы? Этот класс может реализовать IList<DataGridViewRow>
, а затем var
будет работать, но он устарел.
IEnumerable
не передает информацию о типе элемента, а функция GetEnumerator
здесь не помогает, поскольку она возвращает IEnumerator
, тогда как он может вернуть IEnumerator<DataGridViewRow>
.
По сути, компилятор С# ищет функцию GetEnumerator
, которая возвращает объект, который имеет функцию MoveNext
и свойство Current
(или интерфейс IEnumerable<T>
/IEnumerable
при явной реализации). Этот подход duck-typing относится к историческим причинам, он существовал до того, как дженерики были введены в язык. Переменная цикла foreach
будет иметь тот же тип, что и свойство Current
. И в IEnumerator
(не общий вариант), Current
имеет тип object
.
Указание типа явно:
foreach (DataGridViewRow row in myGrid.Rows)
просто возвращает возвращаемое значение Current
в DataGridViewRow
из-за отсутствия лучшего механизма.
Вы также можете использовать LINQ для достижения такого же эффекта, если вы действительно хотите использовать это ключевое слово var
здесь:
foreach (var row in myGrid.Rows.Cast<DataGridViewRow>())
Это работает, потому что метод расширения Enumerable.Cast<T>
возвращает IEnumerable<T>
, который, в свою очередь, использует IEnumerator<T>
, а T
заканчивается как тип Current
перечислителя, поэтому информация типа распространяется.
Я сомневаюсь, что вы воспользуетесь этими деталями на этом этапе, но вы можете захотеть сохранить это для дальнейшего использования, когда узнаете больше о языке. Вам нужно будет узнать о методах расширения и общих типах, чтобы понять это.
DataGridViewRow.Rows
имеет тип DataGridViewRowCollection, который не реализует IEnumerable<DataGridViewRow>
, только IEnumerable
. И object
- лучшее предположение, которое может сделать компилятор, если вы не укажете приведение в DataGridViewRow
для row
Если вы измените DataGridViewRow на Var С#, не уверены, что существует массив, называемый ячейками. Чтобы исправить это, вы можете использовать var как DataGridViewRow, но почти всегда лучше использовать этот тип, если вы его знаете, ищите в Интернете информацию о типе безопасности, чтобы получить дополнительную информацию.