【问题标题】:Using the "clear" method vs. New Object使用“清除”方法与新对象
【发布时间】:2010-06-24 00:43:19
【问题描述】:

在 .NET 框架中,许多 System.Collection 类都有Clear 方法。与用新对象替换引用相比,使用 this 有明显优势吗?

谢谢。

【问题讨论】:

标签: c# .net


【解决方案1】:

如果您有对同一个对象的其他引用,并且您想让它们都指向同一个对象,您会想要使用 Clear

例如,也许您有一个工作队列来存储要执行的任务。并且在一个或多个线程中,您将工作项从该队列中取出(当然,您使用锁定来确保一次最多使用一个线程访问队列)。如果在某个时候您想清空队列,那么您可以使用Clear,所有线程仍将指向同一个对象。

作为seen here,当你使用Clear时,所有项目都将被删除,Count将为0,但Capacity将保持不变。通常Capacity 保持不变是一件好事(为了提高效率),但在某些极端情况下,您可能拥有大量项目并且您希望最终释放这些内存。

上面的 MSDN 链接还提到 Clear 是一个 O(n) 操作。而简单地替换引用将是一个 O(1) 操作,然后最终它将被垃圾收集,但可能不会马上。但是替换引用也意味着构成容量的内存需要重新分配。

【讨论】:

  • 这已经占了大部分,我唯一要补充的是,在处理已经被观看的 ObservableCollections 时,您想使用 Clear。
【解决方案2】:

Brian 是正确的,但更具体地说,Clear 方法从集合的当前实例中删除所有项目。实例化一个新集合并将其引用分配给您的变量将为您提供一个全新的实例,并且可能会导致一些意想不到的后果,具体取决于其他人是否持有对旧实例的引用。如果另一个线程引用了该集合,即使您创建了一个新实例,它们仍将持有对旧集合的引用。

【讨论】:

    【解决方案3】:

    这可能取决于您的集合对象有多大。我认为当您说 new 它将创建对象的原始大小时, clear 只会清除内容但大小仍然相同。

    【讨论】:

      【解决方案4】:

      替换引用不会立即释放集合,它需要等待垃圾收集器处理对象,

      如果您想重新利用同一个对象集合,请使用 .Clear() 否则您将在内存中保留这两个对象一段时间。

      【讨论】:

      • 虽然这是事实,但这并不是大多数人关心的区别。
      • @IgnacioVazquez-Abrams 取决于。我当然会关心收藏是否很大。
      • 但是清除的对象也不会立即被垃圾回收。
      【解决方案5】:

      如果您正在处理大数据并经常操作 IEnumerable 项,则新对象会导致内存问题。看我的例子:

      class Lol
      {
          int i;
          string s;
          public Lol(int ti, string ts)
          {
              i = ti;
              s = ts;
          }
      }
      
      class Program
      {
          static List<Lol> lol = new List<Lol>();
      
          static void Main(string[] args)
          {
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Stopwatch sw = new Stopwatch();
              sw.Start();
              ListCleaner();
              sw.Stop();
              Console.WriteLine(sw.ElapsedMilliseconds);
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
      
              for (int i = 0; i < 10000000; ++i)
                  lol.Add(new Lol(i, i.ToString()));
      
              Console.WriteLine("lol");
      
              ListCleaner();
          }
      
          static void ListCleaner()
          {
              //lol = new List<Lol>();
              lol.Clear();
          }
      }
      

      如果你使用它,你不会在运行时遇到任何问题。但是如果你在 ListCleaner 中注释掉 Clear line 并取消注释 New object line,就会出现内存问题。

      顺便说一句“Console.WriteLine(sw.ElapsedMilliseconds);” (您可以使用 ElapsedTicks,因为它的值与其他值有很大差异。)行告诉您,Clear 需要更多时间,但可以避免内存问题。

      我注意到所有这些都发生在调试代码上(即使是发布模式)。运行.exe文件没有问题。

      【讨论】:

        猜你喜欢
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 2021-02-07
        • 1970-01-01
        相关资源
        最近更新 更多