无法将类型'System.Collections.Generic.List <myproduct>'隐式转换为'System.Collections.Generic.List <t> </t> </myproduct>

时间:2014-04-17 17:03:35

标签: c# generics

我的应用程序使用

var results= websiteDetail.Detail.GetProductDetails<MyProduct>(code, websiteDetail.Detail.NegativeWords);

现在又调用

public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)
{
    List<T> result = new List<T>();
    foreach (var item in GetProducts(negativeWords))
    {
        result.Add((T)Convert.ChangeType(item, typeof(T)));
    }
    return result;
}

private List<MyProduct> GetProducts(List<string> negativeWords)
{
     // logic
}

但是,如果我将代码更新为:

public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)
{
    return GetProducts(negativeWords); //ERROR
}

我被告知:

  
    

无法隐式将'System.Collections.Generic.List<MyProduct>'类型转换为'System.Collections.Generic.List<T>

  

然后我更新了代码,删除List以使用单个对象,同样的问题仍然存在。

为什么当T已经是那种类型时我必须调用ListConvert.ChangeType?

1 个答案:

答案 0 :(得分:1)

这里的问题在于理解C#泛型如何工作。

在C ++中,有一个模板专门化的概念。也就是说,你可以写:

void Foo<T> {}
void Foo<int> {}

如果T是int,它将使用专用版本,否则使用泛型。这在C#泛型中是不允许的。要么一切都是通用的,要么一切都不是。当你写

public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)

你现在处于泛型领域(尽管是通用方法而不是类)。因为你现在处于泛型领域,打电话给特定的函数:

List<MyProduct> GetProducts

没有任何意义。如果T是objectString怎么办?返回MyProduct列表会非常混乱,并且在尝试投射时几乎肯定会失败(正如您的“工作”代码所做的那样)。换句话说,如果你总是返回一个List<MyProduct>,为什么还要使用泛型(因此我之前的评论,它们都需要通用,或者所有具体的,你都不能混合!)。

泛型的一般规则是“T是object”。就是这样,而且一切都可以。如果您需要比object更多的专业化,则需要在泛型类型参数中添加where子句。我有点怀疑你在这种情况下确实需要它,因为你看起来像是在做一个web请求。您应该只需将功能更改为:

List<T> GetProducts

此时您可能还想考虑使该类具有通用性,但这取决于您。如果您无法进行更改,我会从您的方法中删除通用性。你可以在类型oF T上进行切换,但这不是更好,并且很难理解/阅读。

通用类型约束的MSDN(where):MSDN

如果我能说清楚的话,请告诉我!