在C#中返回一个集合的通用类型

3

我定义了一个可以以通用方式实现的接口。返回类型必须是集合,而输入参数可以是类或值。

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

    T GetData(C criteria);
}

当我尝试返回一个List时,出现了一个错误:“由于它没有类类型,因此类型参数T不能与as操作一起使用。” 尝试删除“as T”,但也不起作用。
如果我将T:ICollection<string>替换为List<string>,它就可以工作。这里有什么不正确的?
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;
    }
}
3个回答

4

as 运算符要求 T 是一个引用类型(或可空类型),因此应该在签名中包含对类的约束。

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

{
    T GetData(C criteria);
}

正如Jason在评论中提到的那样,如果T不是字符串类型或派生自T的类型,将返回null。 但是,由于您的约束条件指定预计的ICollection<T>为字符串,因此根据您当前编写的问题,这似乎是可以接受的。


需要注意的是,尽管这在技术上是正确的,但它可能并没有解决任何问题。data as T 对于任何不是 List<string> 或其派生类型的 T 都会返回 null。 - Jason Watkins
@JasonWatkins 很好的观点,虽然它没有在楼主的问题中明确提出,所以我没有提及它。 - David L

2

虽然这不是你所问的问题的答案,但值得注意的是你似乎不理解as运算符。

criteria as string只有在typeof(C)已经是string时才会返回null,使泛型变得毫无意义。

同样地,return data as T;将为任何不是List<string>或从List<string>派生的类型的T返回null。您可以考虑要求一个new()构造函数来允许您直接创建新的T

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;
    }
}

谢谢,这很有帮助。 - Frank Q.
没见过在参数前使用new()符号。看起来很有用。 - Craig.C

1
如果你想将 TC 固定为 List<string>string,则不需要使 CustomADataRetrieverImpl 成为泛型类:
public class CustomADataRetrieverImpl : IDataRetriever<List<string>, string>
{
    public List<string> GetData(string criteria)
    {
        var data = new List<string>();
        ...
        return data;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接