在.NET框架中,许多System.Collection类都有Clear
个方法。使用此方法与使用新对象替换引用有明显的优势吗?
感谢。
答案 0 :(得分:41)
如果您对同一个对象有其他引用,并且希望将它们全部指向同一个对象,则需要使用Clear
。
例如,您可能有一个工作队列,您可以在其中存储要执行的任务。在一个或多个线程中,您将工作项从此队列中取出(当然,您使用锁定以确保一次最多只能访问一个线程的队列)。如果在某些时候你想要清空队列,那么你可以使用Clear
,所有线程仍将指向同一个对象。
当您Clear
使用Count
时,所有项目都将被移除,Capacity
将为0,但Capacity
将保持不变。通常{{1}}保持不变是一件好事(为了效率),但可能会有一些极端情况,你有大量的项目,你希望最终释放内存。
上面的MSDN链接还提到Clear是O(n)操作。而简单地替换引用将是O(1)操作,然后最终它将被垃圾收集,但可能不会立即。但是替换引用也意味着需要重新分配构成容量的内存。
答案 1 :(得分:6)
Brian是正确的,但更具体地说,Clear
方法会从集合的当前实例中删除所有项目。实例化一个新集合并将其引用分配给您的变量将完全为您提供一个全新的实例,并且可能会导致一些意外后果,具体取决于其他人是否持有对旧实例的引用。如果另一个线程具有对该集合的引用,即使您已创建新实例,它们仍将保留对旧集合的引用。
答案 2 :(得分:3)
替换引用不会立即释放集合,它需要等待垃圾收集器处理对象,
如果你想重新使用相同的对象集合,那么使用.Clear()如果没有,你将在内存中有两个对象一段时间。
答案 3 :(得分:3)
这可能取决于你的收藏对象有多大。我认为当你说新的它会创建对象的原始大小时,clear会清除内容,但大小仍然是相同的。
答案 4 :(得分:1)
如果您正在处理大数据并经常操作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,你就会遇到内存问题。
顺便说一句&#34; Console.WriteLine(sw.ElapsedMilliseconds);&#34; (您可以使用ElapsedTicks,因为它的值与其他值非常不同。)行告诉您,Clear需要更多时间,但可以避免内存问题。
我注意到所有这些都发生在调试代码上(即使是发布模式)。运行.exe文件没有问题。