Уважаемые друзья,
извините, если вопрос покажется простоват. Отличается ли поведение сборщика мусора в .NET в следующих случаях (C# приложение):
1.
{
...
Class1 cls1 = getClass1();
Class2 cls2 = cls1.getClass2();
Class3 cls3 = cls2.getClass3();
cls3.someMethod();
...
}
и вот такого
2.
{
...
getClass1().getClass2().getClass3().someMethod();
...
}
Заранее спасибо за любой полезный совет.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, dsbalbor, Вы писали:
Оптимизирующий компилятор сведет первый случай ко второму.
А вообще же объекты на стеке являются GC protected.
Без оптимизации для исполнения этого блока
{
Class1 cls1 = getClass1();
Class2 cls2 = cls1.getClass2();
Class3 cls3 = cls2.getClass3();
cls3.someMethod();
}
нужно три элемента стека.
А для этого
getClass1().getClass2().getClass3().someMethod();
один элемент.
Здравствуйте, dsbalbor, Вы писали:
D>Заранее спасибо за любой полезный совет.
Выше уже ответили, но самый простой способ разобраться — запустить без отладчика -debug и -release сборки
| вот этого кода: |
| using System;
using System.Runtime.CompilerServices;
using System.Threading;
public class Program
{
private static readonly string offset = new string('\t', 4);
class A
{
public A()
{
Console.WriteLine(offset + "new A()");
}
~A()
{
Console.WriteLine(offset + "~A()");
}
public B GetB() { return new B(); }
}
class B
{
public B()
{
Console.WriteLine(offset + "new B()");
}
~B()
{
Console.WriteLine(offset + "~B()");
}
public C GetC() { return new C(); }
}
class C
{
public C()
{
Console.WriteLine(offset + "new C()");
}
~C()
{
Console.WriteLine(offset + "~C()");
}
public D GetD() { return new D(); }
}
class D
{
public D()
{
Console.WriteLine(offset + "new D()");
}
~D()
{
Console.WriteLine(offset + "~D()");
}
}
private static void FullGC(bool inMethod)
{
var oldColor = Console.ForegroundColor;
try
{
Console.ForegroundColor = inMethod ? ConsoleColor.Green : ConsoleColor.Red;
Console.WriteLine("\tRun GC {");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("\t}");
}
finally
{
Console.ForegroundColor = oldColor;
}
}
static void Main(string[] args)
{
AsVariables();
FullGC(false);
Console.WriteLine("------------");
Console.WriteLine("");
AsVariablesNull();
FullGC(false);
Console.WriteLine("------------");
Console.WriteLine("");
CallChain();
FullGC(false);
Console.WriteLine("------------");
Console.WriteLine("");
Console.Write("Done.");
Console.ReadKey();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void AsVariables()
{
Console.WriteLine("-> Enter AsVariables()");
var a = new A();
var b = a.GetB();
var c = b.GetC();
var d = c.GetD();
FullGC(true);
Console.WriteLine("<-Exit AsVariables()");
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void AsVariablesNull()
{
Console.WriteLine("-> Enter AsVariablesNull()");
var a = new A();
var b = a.GetB();
var c = b.GetC();
var d = c.GetD();
a = null;
b = null;
c = null;
d = null;
FullGC(true);
Console.WriteLine("<- Exit AsVariablesNull()");
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void CallChain()
{
Console.WriteLine("-> Enter CallChain()");
var d = new A().GetB().GetC().GetD();
FullGC(true);
Console.WriteLine("<- Exit CallChain()");
}
}
|
| |
Дальше открываем ilspy/reflector или любой декомпилятор по вкусу и смотрим на разницу в il.
Самое интересное — поведение release-версии
под отладчиком.
Я на него наткнулся года три назад, у нас был хитрый баг, который с трудом, но воспроизводился на релизной сборке. И в принципе не ловился на той же сборке под отладчиком.
Вот
схема возможных раскладов, нас интересует верхний правый угол. В моём случае "D" не был унаследован от CriticalFinalizerObject, что иногда приводило к неправильному порядку вызова деструкторов.
Здравствуйте, c-smile, Вы писали:
CS>А вообще же объекты на стеке являются GC protected.
Только в первом приближении.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>