Приведение из отфильтрованного пользовательского списка <T>с помощью LINQ - PullRequest
3 голосов
/ 12 октября 2009

У меня есть собственный список, который наследуется от Generic.List<T>, например:

public class TransferFileList<T> : List<TransferFile> { .. }

Когда я устанавливаю (где Files - TransferFileList<T>):

var files = uploadResponse.Files.Where(x => !x.Success).ToList()

объект 'files' разрешается как System.Collections.Generic.List<TransferFile>, а не TransferFileList<T>, что я и ожидал, поскольку это было то, что фильтровалось через Where, так как же я мог успешно вернуть список TransferFileList<T> в «файлы»?

Я попробовал:

var files = uploadResponse.Files.Where(x => !x.Success).ToList() 
as TransferFileList<TransferFile>;

но при использовании этого безопасного приведения он просто разрешается как ноль.

Спасибо, ребята и девочки.

Ответы [ 3 ]

2 голосов
/ 12 октября 2009

Сначала я должен спросить, почему вы наследуете от List<T>? 99% времени это плохая идея.

Если вы хотите расширить функциональность списка, используйте методы расширения:

public static something PrintErrors(this List<TransferFile> list)
{
    //do your printing logic
}

Об ответе: ToList() работает с IEnumerable<T> и преобразует члены последовательности в List того же типа. Поскольку вы наследуете от List<T>, который реализует IEnumerable<T>, вот что происходит там.

Where() работает так же - работает на IEnumerable<T> и возвращает IEnumerable<T>.

Чтобы вернуть какой-либо произвольный объект, похожий на список, как у вас, вам нужно добавить элементы в последовательности в ваш пользовательский список, например:

var myFiles = new TransferFileList<TransferFile>();
myFiles.AddRange(originalFileList.Where(condition));
1 голос
/ 12 октября 2009

Вы можете добавить метод расширения для IEnumerable<TransferFile> для обработки этого сценария:

public static TransferFileList ToTransferFileList(
    this IEnumerable<TransferFile> files)
{
    return new TransferFileList(files);
}

// ...

var files = uploadResponse.Files.Where(x => !x.Success).ToTransferFileList(); 

Это дает вам TransferFileList вместо List<TransferFile>. Обратите внимание, что причина, по которой as возвращает null, заключается в том, что хотя TransferFileList равно List<TransferFile>, то же самое не сохраняется в другом направлении. То есть ваш List<TransferFile> НЕ является TransferFileList объектом.

Я согласен с @RexM, чтобы избежать любых попыток создания подкласса List<T> из-за множества связанных с этим ошибок. Я предлагаю Composition (Has-A, а не Is-A) или придерживаться коллекций библиотек базовых классов.

0 голосов
/ 12 октября 2009

Спасибо, ребята.

Мне нравится подход расширения SLV, но есть ли другой подход прямого литья?

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

var transferFiles = new TransferFileList<TransferFile>();
if (files != null) 
  transferFiles.AddRange(files);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...