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);
加载中,请稍侯......
精彩评论