И ответ: да, если вы знаете, что делаете! Но это преждевременная оптимизация (корень всех зол для многих людей), поэтому вам не следует делать это, если вам действительно не нужна память.
Теперь я проанализирую только два случая, когда это может быть полезно.
Свойства объекта, на который вы знаете, больше не будут ссылаться (например, вы кэшировали некоторые сложные вычисления в частном свойстве. Вы знаете, что вам больше не нужно, вы чистите его) Но об этом было сказано многими людьми
Поля в сложных методах. Это противоположно тому, что сказали другие, но у меня есть пример, поэтому я знаю, что я прав :-) Теперь, обычно, в последовательном методе , GC может видеть, где локальная ссылка больше не используется (технически важная часть - это когда он больше не читается. И вызов методов переменной - это «чтение». Запись в переменную не считается, потому что если никто не будет читать новое значение, писать бесполезно она)
Но я сказал последовательный метод . И непоследовательные методы? Давай попробуем! (ясно, что я уже сделал это! Я не буду делать пример ideone , потому что GC mono отличается от GC из .NET).
Скомпилируйте этот фрагмент кода в режиме Release и запустите без отладчика (т. Е. CTRL-F5) и просмотрите результаты:
using System;
namespace ConsoleApplication17
{
class Program
{
static void Main()
{
const int cycles = 1000000;
{
string str = new string(' ', 10000000);
Console.WriteLine("Let's see when the GC will free the memory");
Console.WriteLine("Start: {0}", GC.GetTotalMemory(true));
for (int i = 0; i < 1000000; i++)
{
if (i == cycles - 1)
{
Console.WriteLine("Near end: {0}", GC.GetTotalMemory(true));
}
//Here we reference the string,
//but only in the first 100 iterations
if (i < 100 && str[str.Length - 1] == 'c')
{
throw new Exception();
}
}
Console.WriteLine("End: {0}", GC.GetTotalMemory(true));
}
Console.WriteLine();
{
string str = new string(' ', 10000000);
Console.WriteLine("Let's do the work for him");
Console.WriteLine("Start: {0}", GC.GetTotalMemory(true));
for (int i = 0; i < 1000000; i++)
{
if (i == cycles - 1)
{
Console.WriteLine("Near end: {0}", GC.GetTotalMemory(true));
}
//Here we reference the string,
//but only in the first 100 iterations
if (i < 100 && str[str.Length - 1] == 'c')
{
throw new Exception();
}
else if (i == 100)
{
str = null;
Console.WriteLine("Just nullified the string: {0}", GC.GetTotalMemory(true));
}
}
Console.WriteLine("End: {0}", GC.GetTotalMemory(true));
}
Console.ReadKey();
}
}
}
Результаты:
Let's see when the GC will free the memory
Start: 20042264
Near end: 20042888
End: 42872
Let's do the work for him
Start: 20042888
Just nullified the string: 42872
Near end: 42872
End: 42872
Объяснение: эта программа является примером циклической программы, в которой большой объект инициализируется вне цикла (цикл for
), а большой объект используется только в части цикла (например, в первых 100 итераций). Ясно, что GC не может легко увидеть, что с конца итерации 99 (сотая итерация, 0-99) и далее на объект не будут ссылаться.
Но помните слова преждевременная оптимизация и корень всех зол ! : -)