여기서 누락 된 것은 컴파일러가 x정의 된 메소드의 끝까지 컴파일러의 변수 수명을 연장 한다는 것입니다. 즉 컴파일러가하는 일 이지만 DEBUG 빌드를 위해서만 수행합니다.
변수가 별도의 방법으로 정의되도록 코드를 변경하면 예상대로 작동합니다.
다음 코드의 출력은 다음과 같습니다.
False
True
그리고 코드 :
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
test();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True.
}
static void test()
{
new Finalizable();
}
}
}
그래서 기본적으로 이해는 정확했다,하지만 당신은 때까지 몰래 컴파일러가 변수 살아 계속가는 것을 몰랐다 후 당신이 전화 GC.Collect()- 당신이 명시 적으로 널 (null)로 설정 한 경우에도!
위에서 언급했듯이 이것은 DEBUG 빌드에서만 발생합니다. 아마도 메소드의 끝으로 디버깅하는 동안 로컬 변수의 값을 검사 할 수 있습니다 (그러나 추측 일뿐입니다!).
원래 코드는 릴리스 빌드에서 예상대로 작동하므로 false, trueRELEASE 빌드 및 false, falseDEBUG 빌드에 대해 다음 코드 출력 이 있습니다 .
using System;
namespace ConsoleApp1
{
class Finalizable
{
~Finalizable()
{
_extendMyLifetime = this;
}
public static bool LifetimeExtended => _extendMyLifetime != null;
static Finalizable _extendMyLifetime;
}
class Program
{
public static void Main()
{
new Finalizable();
Console.WriteLine(Finalizable.LifetimeExtended); // False.
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine(Finalizable.LifetimeExtended); // True iff RELEASE build.
}
}
}
부록으로 : 종료 된 객체에 대한 참조가 프로그램 루트에서 도달 할 수 있도록하는 클래스에 대해 finalizer에서 무언가를 수행하면 해당 객체가 더 이상 존재하지 않을 때까지 해당 객체는 가비지 수집되지 않습니다. 참조.
즉, 종료자를 통해 개체에 "실행 상태"를 제공 할 수 있습니다. 그러나 이것은 일반적으로 나쁜 디자인으로 유지됩니다!
예를 들어, 위 코드 _extendMyLifetime = this에서 finalizer에서 수행 하는 객체에 대한 새 참조를 작성하므로 이제는 _extendMyLifetime더 이상 참조하지 않을 때까지 가비지 수집 되지 않습니다.
Person1입니까? 나만 볼 수Person있습니다. 마지막 : 파이널 라이저 작동 방식 은 docs.microsoft.com/dotnet/csharp/programming-guide/… 를 참조하십시오 .