开发者

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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜