Почему этот актерский состав не работает? - PullRequest
7 голосов
/ 08 августа 2011

Этот код работает:

foreach(DataColumn column in table.Columns)
{
    // do whatever
}

Но этот код не:

(IEnumerable<DataColumn>)(table.Columns)

Свойство .Columns возвращает DataColumnCollection , который является InternalDataCollectionBase , который реализует IEnumerable, поэтому он должен работать.

Я получаю ошибку

Невозможно преобразовать тип 'System.Data.DataColumnCollection' в 'System.Collections.Generic.IEnumerable'

Ответы [ 5 ]

19 голосов
/ 08 августа 2011

DataColumnCollection реализует IEnumerable, и каждая возвращаемая строка равна a DataColumn, но не реализует IEnumerable<DataColumn>. Поскольку он не реализует интерфейс, вы не можете привести к интерфейсу. Поскольку класс запечатан, компилятор знает , что значение не может реализовать интерфейс, поэтому вы даже не можете преобразовать его во время компиляции.

Используйте метод LINQ Cast:

table.Columns.Cast<DataColumn>()

Это эффективный метод адаптера - каждый элемент в коллекции столбцов будет лениво приведен к DataColumn, когда вы извлекаете его из результата.

Причина компиляции foreach заключается в том, что компилятор добавляет явное приведение для вас. Например, это будет compile :

foreach (string x in table.Columns)
{
}

... но он выдаст исключение во время выполнения.

3 голосов
/ 08 августа 2011

Это потому, что DataColumnCollection реализует IEnumerable, но не IEnumerable<T>.

var columns = (IEnumerable)(table.Columns) должно работать

IEnumerable и IEnumerable никак не связаны.(однако IEnumerable<DataColumn> наследуется от IEnumerable<object>, который может быть напечатан как утка в IEnumerable с использованием динамического, но это не очень помогает вам (даже если это очень весело))

1 голос
/ 08 августа 2011

В первом случае вы каждый раз индивидуально обрабатываете коллекцию Columns, но во втором случае вы разыгрываете всю коллекцию одновременно. Это действительно ничем не отличается от:

// Cats implements IAnimal
Cats[] cats = new Cats[20]; 
...
IAnimal animal = cats[0];

против

// this you cannot do
Cats[] cats = new Cats[20]; 
IAnimal[] animal = cats;

Однако, это спорный вопрос, так как вы можете сделать это:

table.Columns.Cast<DataColumn>()

И покончим с этим. Обратите внимание, что использование Cast<> предпочтительнее простого получения универсального IEnumerable, так как строгая типизация сохраняется.

0 голосов
/ 08 августа 2011

Попробуйте это:

var columns = table.Columns as IEnumerable;
0 голосов
/ 08 августа 2011

Это потому, что DataColumnCollection реализует только IEnumerable, поэтому вы не можете привести его к универсальной версии IEnumerable<DataColumn>.При использовании foreach компилятор выполняет кастинг для каждого элемента по соглашению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...