Cast from filtered custom List<T> with LINQ
I have a custom list which inherits from Generic.List<T>
like this:
public class TransferFileList<T> : List<TransferFile> { .. }
When I set (where 'Files
' is a TransferFileList<T>
):
var files = uploadResponse.Files.Where(x => !x.Success).ToList()
the 'files
' object resolves as System.Collections.Generic.List<TransferFile>
, not TransferFileList<T>
, which is what I wou开发者_如何学编程ld expect as it was what was being filtered through the Where
, so how could I successfully return a list of TransferFileList<T>
into 'files'?
I did try:
var files = uploadResponse.Files.Where(x => !x.Success).ToList()
as TransferFileList<TransferFile>;
but using that safe cast, it just resolves as null.
Thanks guys and gals.
First, I have to ask why you are inheriting from List<T>
? 99% of the time that's a bad idea.
If you want to extend the functionality of a list, use extension methods:
public static something PrintErrors(this List<TransferFile> list)
{
//do your printing logic
}
On to the answer: ToList()
operates on an IEnumerable<T>
and converts the members of the sequence to a List
of the same type. Since you inherit from List<T>
which implements IEnumerable<T>
, that's what happens there.
Where()
works the same way - operates on an IEnumerable<T>
and returns an IEnumerable<T>
.
To get some arbitrary list-like object back, like you have, you need to add the items in a sequence to your custom list, like so:
var myFiles = new TransferFileList<TransferFile>();
myFiles.AddRange(originalFileList.Where(condition));
You can add an extension method for IEnumerable<TransferFile
> to handle that scenario:
public static TransferFileList ToTransferFileList(
this IEnumerable<TransferFile> files)
{
return new TransferFileList(files);
}
// ...
var files = uploadResponse.Files.Where(x => !x.Success).ToTransferFileList();
This provides you with the TransferFileList
instead of just a List<TransferFile>
. Note the reason your as
returns null
is because while TransferFileList
is a List<TransferFile>
, the same does not hold in the other direction. That is, your List<TransferFile>
is NOT a TransferFileList
object.
I agree with @RexM that any attempt at subclassing List<T>
be avoided due to the multitude of pitfalls associated. I suggest Composition (Has-A rather than Is-A) or sticking with the base class library collections instead.
Thanks guys.
I like SLV's extension approach, but is there any other straight casting approach?
If not I might just go with the reverted in-line approach I was hoping to avoid:
var transferFiles = new TransferFileList<TransferFile>();
if (files != null)
transferFiles.AddRange(files);
精彩评论