【问题标题】:Cannot implicitly convert List<T> to Collection<T>无法将 List<T> 隐式转换为 Collection<T>
【发布时间】:2010-10-06 04:23:11
【问题描述】:

这是一个编译器错误(为了便于阅读,稍作改动)。

这个总是让我很困惑。 FxCop 告诉我们返回 List 是一件坏事,而从Collection&lt;T&gt; 派生的类应该作为返回类型更受欢迎。

此外,FxCop 表示可以使用List&lt;T&gt; 进行内部数据存储\操作。 好的,我明白了,但我不明白的是编译器抱怨试图将List&lt;T&gt; 隐式转换为Collection&lt;T&gt;List&lt;T&gt; 不是更有接口和功能吗? 为什么要禁止隐式转换?

还有一个源于上面的问题:new List&lt;int&gt;(some collection&lt;int&gt;) 构造函数是否昂贵?

谢谢,

瓦伦丁·瓦西里耶夫

【问题讨论】:

    标签: c# generics collections


    【解决方案1】:

    为什么不直接做以下事情:

    Collection<string> collection = new Collection<string>(theList);
    

    因为 Collection(IList 输入) 将 List 作为构造的一部分。

    【讨论】:

      【解决方案2】:

      List&lt;T&gt; 不是从 Collection&lt;T&gt; 派生的 - 但是,它确实实现了 ICollection&lt;T&gt;。这将是一个更好的返回类型选择。

      至于new List&lt;int&gt;(some collection&lt;int&gt;) 问题-部分取决于集合是什么。如果它实现了ICollection&lt;T&gt;(在执行时),那么构造函数可以使用它的Count 属性来创建具有正确初始容量的列表,然后再遍历它并添加每个项目。如果它没有实现ICollection&lt;T&gt; 那么它就相当于:

      List<int> list = new List<int>();
      foreach (int x in otherCollection)
      {
          list.Add(x);
      }
      

      在一个方便的构造函数中仍然很好,但效率不高 - 真的不可能。

      我不相信构造函数对数组做了任何狡猾的事情,它可能会 - 使用 Array.Copy 或其他任何东西来一次性复制很多而不是迭代。 (同样,如果它是另一个 List&lt;T&gt;,它可以获取支持数组并直接复制它。)

      【讨论】:

        【解决方案3】:

        List&lt;T&gt; 不继承自 Collection&lt;T&gt;。干净利落。除非List&lt;T&gt; 提供一个运算符来隐式转换到Collection&lt;T&gt;,否则你不能这样做。如果可以的话,我实际上建议返回List&lt;T&gt;,因为我相信规则是这样的:

        接受尽可能少的约束接口作为参数。 作为返回参数返回尽可能严格的类型。

        【讨论】:

          【解决方案4】:

          这是一个用 C# 3.0 编写的通用扩展方法,用于将List&lt;T&gt; 转换为Collection&lt;T&gt;

          using System.Collections.Generic;
          using System.Collections.ObjectModel;
          
          public static class ExtensionMethods
          {
              public static Collection<T> ToCollection<T>(this List<T> items)
              {
                  Collection<T> collection = new Collection<T>();
          
                  for (int i = 0; i < items.Count; i++)
                  {
                      collection.Add(items[i]);
                  }
          
                  return collection;
              }
          }
          

          而且是这样使用的……

          List<string> entities = new List<string>();
          entities.Add("Value 1");
          entities.Add("Value 2");
          entities.Add("Value 3");
          entities.Add("Value 4");
          
          Collection<string> convertedEntities = entities.ToCollection<string>();
          

          【讨论】:

            【解决方案5】:

            这是您从 List&lt;T&gt; 转换为 Collection&lt;T&gt; 的方式(使用 LINQ 时):

            旧功能:

            public List<Employee> GetEmployee(int id)
            {
                 return ( from e in MyDataContext.Employees
                               select new Employee()
                               {
                                 e.empId = id
                               }
                         ).ToList();
            }
            

            转换后:

            using System.Collection.ObjectModel;
            
            public Collection<Employee> GetEmployee(int id)
            {
                       return new Collection<Employee>( 
                           (from e in MyDataContext.Employees
                                 select new Employee()
                                 {
                                   e.empId = id
                                 }
                            ).ToList() as IList<Employee>
                       );
            }
            

            【讨论】:

            • 作为 IList 谢谢@Shadi Namrouti
            【解决方案6】:

            你可以使用下面的

            public class EmployeeCollection : Collection<Employee>
            {
                  public EmployeeCollection(IList<Employee> list) : base(list)
                  {}
            
                  public EmployeeCollection() : base()
                  {}
            
            }
            

            像这样使用类

            EmployeeCollection  employeeCollection = new EmployeeCollection(list)
            

            【讨论】:

              【解决方案7】:

              反之,不需要循环...你可以只做.ToList()

                  ICollection<T> collection = new Collection<T>();
              

              使用任何方法填充您的收藏,当您需要列表时,只需这样做:

                  List<T> list = collection.ToList();
              

              之后,您可以在列表中使用任何您想要的内容。

              好好编码!

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-12-09
                • 2019-12-02
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-06-11
                相关资源
                最近更新 更多