Frank Q.
Frank Q.

Reputation: 6592

Returning a generic type that is a collection in C#

I have defined an interface that can be implemented in a generic way. The return type has to be a collection where as the input parameter can be a class or value.

public interface IDataRetriever<T, C> where T : ICollection<string>
{

    T GetData(C criteria);
}

When I try to return a List I am getting an error "type parameter T cannot be used with the as operation because it does not have a class type." Tried removing the "as T" but that did not work either.

If I replace where T : ICollection<string> with List<string> it works. What is incorrect here ?

public class CustomADataRetrieverImpl<T, C>: IDataRetriever<T, C> 
             where T : ICollection<string>
{

    public T GetData(C criteria)
    {

        string myCriteria = criteria as string;
        ICollection<string> data = new List<string>()
            ...
        return data as T;
    }
}

Upvotes: 3

Views: 100

Answers (3)

David L
David L

Reputation: 33815

as expects T to be a reference (or nullable) type, which means that a constraint to class should also be included in your signature.

public interface IDataRetriever<T, C>
    where T : ICollection<string>, class

{
    T GetData(C criteria);
}

As Jason mentioned in the comments, if T is anything other than a string type or a type derived from T, null will be returned. However, since your constraint specifies that you expect ICollection<T> to be string, this seems acceptable as your question is currently written.

Upvotes: 4

Lee
Lee

Reputation: 144126

If you want to fix T and C to List<string> and string you don't need to make CustomADataRetrieverImpl generic:

public class CustomADataRetrieverImpl : IDataRetriever<List<string>, string>
{
    public List<string> GetData(string criteria)
    {
        var data = new List<string>();
        ...
        return data;
    }
}

Upvotes: 1

Jason Watkins
Jason Watkins

Reputation: 3785

Not the answer to the question you asked, but it's worth noting that you don't seem to understand the as operator.

criteria as string will return null unless typeof(C) is already string, making the generic worthless.

Likewise, return data as T; will return null for any T that is not List<string> or a type derived from List<string>. You could consider requiring a new() constructor to allow you to create a new T directly.

public class CustomADataRetrieverImpl<T, C>: IDataRetriever<T, C> 
             where T : ICollection<string>, new()
{

    public T GetData(C criteria)
    {

        string myCriteria = criteria.ToString();
        T data = new T()
            ...
        return data;
    }
}

Upvotes: 2

Related Questions