简体   繁体   中英

Casting List<[KnownType]> to List<T> to match function's return type?

I am trying to make a function that generically retrieves data from my MongoDB collections. To do this I have constructed a generic method that returns a List<T> .

My issue is that I have to create this List<T> to return, but I do so based on the typeof T . I am not sure what I need to do to please the compiler..

public async Task<List<T>> GetDocsAsync<T>(
    CollectionTypes collection, // Enum representing my Collections
    FilterDefinition<BsonDocument> search, 
    SortDefinition<BsonDocument> sort = null)
{
    // Get BsonDocuments from the collection based on the search and sort criteria 
    List<BsonDocument> matchedDocs;
    IMongoCollection<BsonDocument> MongoCollection = GetCollection(collection);
    if (sort == null) matchedDocs = await MongoCollection.Find(search).ToListAsync();
    else matchedDocs = await MongoCollection.Find(search).Sort(sort).ToListAsync();

    // Return a List<T>, covert matchedDocs to List<T> if need be
    Type docType = typeof(T);
    if (docType == typeof(BsonDocument))
        return matchedDocs;
    else if (docType == typeof(LogEvent_DBDoc))
        return LogEvent_DBDoc.ConvertFromBson(matchedDocs);
    // ...
}

At both of the return lines I receive an error along the lines of "Cannot implicitly convert from List<[KnownType]> to List<T> . Which makes sense to me, because the typeof T does not necessarily match the typeof say BsonDocument . But I have made the proper check to do so.

Can I cast List<[KnownType]> to List<T> ?

You are abusing generic syntax. Generic code should be generic , ie work with whatever type you use.

You should have different methods, depending on the type that will be passed in. By all means, make the truly generic parts into its own generic method, which your type-specific methods can call. But have the caller, who already knows what type it's using, pick the appropriate method based on that type, and then just use that type explicitly in each type-specific method.

It's hard to say with the example you have, but if you can provide a good Minimal, Complete, and Verifiable example that shows clearly what you're doing, I would be happy to refactor it to show what I mean.

If you're sure you have the List<KnownType> that matches the type of current generic instantiation of List<T> you can cast it to the required generic type with the help of intermediate cast to object :

List<T> GetListOf<T>() {
    if (typeof(T) == typeof(String)) {
        var stringList = new List<String> { "a", "b" };
        return (List<T>)(object)stringList;
    }
    throw new NotSupportedException();
}

Leaving the moral judgement whether you should do so to yourself )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM