Подтвердить что ты не робот

Как передать List <object> в список <SomethingElse>

Как я могу отнести List<object> к List<SomethingElse>?

(где SomethingElse, как известно, опускается из object)


Бонус-чат

Листинг списка:

List<Object> first = ...;

List<SomethingElse> second = (List<SomethingElse>)first;

не работает:

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

Листинг списка:

List<SomethingElse> second = first.Cast<SomethingElse>();

не работает:

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

Мне действительно не нужен полный объект List<T>, просто выполните ICollection<T>:

ICollection<SomethingElse> second = first;
ICollection<SomethingElse> second = (ICollection<SomethingElse>)first;
ICollection<SomethingElse> second = first.Cast<SomethingElse>();

не работают.

4b9b3361

Ответ 1

LINQ, реализованный с помощью методов расширения класса Enumerable, зависит от отложенного выполнения:

Методы, которые используются в запросе, который возвращает последовательность значений, не потребляют целевые данные до тех пор, пока объект запроса не будет перечислен. Это называется отсроченным исполнением.

Cast<T> не создает новый список сразу, а скорее сохраняет всю информацию, необходимую для выполнения действия. Список будет отображаться только при необходимости (например, с помощью инструкции foreach).

В вашем случае, если вы просто намереваетесь итерации по последовательности, вы должны подумать о том, чтобы придерживаться интерфейса IEnumerable<T>, который является объявленным типом возврата Cast<T>:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
foreach (SomethingElse se in second)
{
    // ...
}

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

Если вы уверены, что хотите создать новый список сразу, используйте ToList:

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

Изменить: ответ на сообщение, отправленное в комментарии:

Это зависит от того, что вы подразумеваете под "списком, который можно изменить". Существует несколько операторов запросов LINQ, которые позволят вам дополнительно изменить определение вашего запроса. Например, если вы хотите удалить все элементы SomethingElse, чье свойство IsDeleted true, вы можете использовать оператор Where:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
second = second.Where(element => !element.IsDeleted);

Если вы хотите добавить последовательность новых элементов, вы можете использовать оператор Concat:

second = second.Concat(anotherCollectionOfSomethingElse);

Если вы хотите отсортировать свою последовательность в порядке возрастания ID, используйте оператор OrderBy:

second = second.OrderBy(element => element.ID);

Каждый раз, применяя оператор запроса к прежнему определению нашего запроса и присваивая новый (составной) запрос нашей переменной second. LINQ будет хранить все ваши операторы в определении запроса. Затем, когда последовательность фактически перечисляется (например, через foreach или ToList), она даст вам составной результат вашей последовательности, при этом все операторы запроса будут применены в порядке.

Как и во всех случаях отложенного исполнения/ленивой оценки, будьте осторожны, чтобы не переходить за борт с этим. Если, например, вы собираетесь применить оператор Where, который резко сократит размер вашей последовательности, может быть целесообразно выполнить запрос с нетерпением и вместо этого сохранить список.

Ответ 2

Я думаю, что вы близки к выражению Cast<T>. Разница в том, что Cast<T> возвращает IEnumerable<T>, а не List<T>.

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

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();

Вы можете получить список, выполнив что-то подобное:

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

Ответ 3

У вас есть возможность использовать либо Cast, либо OfType. Cast выдаст исключение, если вы не можете применить его к указанному типу. OfType, с другой стороны, возвратит только те элементы в списке, которые могут быть приведены к указанному типу. Я бы рекомендовал использовать OfType в вашей ситуации.

List<Foo> fooList = myList.OfType<Foo>().ToList();