【问题标题】:Can use IList but not List in generic method可以在泛型方法中使用 IList 但不能使用 List
【发布时间】:2013-03-24 20:13:32
【问题描述】:

我正在尝试创建一个方法,该方法返回用户想要的任何类型的列表。为此,我使用了泛型,我不太熟悉,所以这个问题可能很明显。问题是这段代码不起作用并抛出错误消息Cannot convert type Systems.Collections.Generic.List<CatalogueLibrary.Categories.Brand> to Systems.Collection.Generic.List<T>

private List<T> ConvertToList<T>(Category cat)
{            
     switch (cat)
     {
         case Category.Brands:
             return (List<T>)collection.Brands.ToList<Brand>();

     }
    ...
}

但如果我改用IList,则没有错误。

private IList<T> ConvertToList<T>(Category cat)
{            
     switch (cat)
     {
         case Category.Brands:
             return (IList<T>)collection.Brands.ToList<Brand>();

     }
     ...
} 

为什么在这种情况下我可以使用 IList 而不是 List? collection.Brands 从第三方库返回 BrandCollection 类型,所以我不知道它是如何创建的。难道BrandCollection 可能源自 IList(只是猜测它确实如此),因此它可以转换为它,但不能转换为普通的 List?

【问题讨论】:

  • 你应该把类型限制在那里,伙计!你不能无所事事地到处铸造东西。
  • 你确定你的第二个例子不是return (IList&lt;T&gt;)collection.Brands.ToList&lt;T&gt;();
  • 我打算在这工作后进行调查。我对泛型有点陌生,所以我想我会把它留到以后,以防它破坏其他东西:D 约束是where T : Brand(和其他类别)吗?
  • 我觉得你这里的通用用法不正确。
  • @Matthew - 我尝试使用 ToList 但我得到了Instance argument: cannot convert from '..BrandCollection' to 'System.Collections.Generic.IEnumerable&lt;T&gt;'

标签: c# list generics interface ilist


【解决方案1】:

由于T没有约束,所以只能在编译时转换为object。编译器不会检查对接口类型的强制转换,因为理论上可能会创建一个实现IList&lt;object&gt; 并继承List&lt;Brand&gt; 的新类。但是,转换为List&lt;T&gt; 将失败,因为已知不能创建继承List&lt;object&gt;List&lt;Brand&gt; 的类。但是,在您的情况下,您通过 switch 语句知道 T 的类型并希望强制转换。为此,请先通过object 进行转换,如下所示:

private List<T> ConvertToList<T>(Category cat)
{            
    switch (cat)
    {
        case Category.Brands:
            return (List<T>)(object)collection.Brands.ToList<Brand>();
    }
}

不过,这里更大的设计问题是,当您拥有T 的已知类型的离散列表时,泛型并不是最佳选择。当T 可以是任何东西,或者被限制为基本类型或接口时,泛型会更好。在这里,你最好只为 switch 语句的每个分支编写一个单独的方法:

private List<Brand> ConvertToBrandList()
{
    return collection.Brands.ToList<Brand>();
}

没有这个,你几乎没有类型安全。如果有人用ConvertToList&lt;int&gt;(Category.Brands) 调用你的方法怎么办?

【讨论】:

  • 感谢您的解释。虽然object 方法有效,但我会选择单独的方法路线。我无法限制到Brand,因为我刚刚发现它是一个密封类。
  • +1。我认为真正的原因是由于 C# 参考 6.2.4:“显式参考转换是......从 any class-type Sany interface-type T,前提是 S 没有密封,并且 S 没有实现 T。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多