Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 垃圾收集和对象初始值设定项_C#_Garbage Collection - Fatal编程技术网

C# 垃圾收集和对象初始值设定项

C# 垃圾收集和对象初始值设定项,c#,garbage-collection,C#,Garbage Collection,在本例中,如果对象是在GC收集后用构造函数初始化的,则将从堆中删除收集对象,但使用对象初始值设定项,则收集后引用将处于活动状态。 为什么@is==false和@is2==true? 为什么weak2在GC.Collect之后仍然有object,而weak没有?出现这个问题是因为您对垃圾收集器的行为做出了假设,而C语言规范没有强制要求这样做。特别是,您假设传递给WeakReference构造函数的每个对象都有资格在下一行进行垃圾收集。这不是一个正确的假设;事实上,C编译器实际上会产生两种不同的行为

在本例中,如果对象是在GC收集后用构造函数初始化的,则将从堆中删除收集对象,但使用对象初始值设定项,则收集后引用将处于活动状态。 为什么@is==false和@is2==true?
为什么weak2在GC.Collect之后仍然有object,而weak没有?

出现这个问题是因为您对垃圾收集器的行为做出了假设,而C语言规范没有强制要求这样做。特别是,您假设传递给WeakReference构造函数的每个对象都有资格在下一行进行垃圾收集。这不是一个正确的假设;事实上,C编译器实际上会产生两种不同的行为,这取决于您是否启用了优化,并且两者都不比另一种更正确

注:以下评估是使用Roslyn CTP for Visual Studio 2013和2013执行的

禁用优化代码 启用优化后,中间值实际上存储在专门为其创建的临时局部变量中。特定的行是IL_0042:stloc.s 9行,它将对象存储在局部变量[9]中。此变量在使用后不会设置为null,因此在Main方法返回之前,引用实际上会阻止对象被垃圾收集

class Program
{
    static void Main(string[] args)
    {
        var test = new Test { Name = "One" };
        var test2 = new Test { Name = "Two" };
        var weak = new WeakReference<TestRef>(new TestRef(test, test2));
        var weak2 = new WeakReference<TestRef>(new TestRef(test) { Test2 = test2 });
        GC.Collect();

        TestRef tref;
        TestRef tref2;
        var @is = weak.TryGetTarget(out tref); //FALSE
        var @is2 = weak2.TryGetTarget(out tref2); //TRUE
    }
}

class Test
{
    public Test()
    { }
    public string Name { get; set; }
}

class TestRef
{
    public TestRef(Test test)
    { Test = test; }

    public TestRef(Test test, Test test2)
    {
        Test = test;
        Test2 = test2;
    }
    public Test Test { get; set; }
    public Test Test2 { get; set; }
}

我有一个简短的答案:我在这里发现的唯一问题是是否有人有一个简短的答案。请再读一遍我的评论。你有问题吗PSorry,问题是:为什么@is==false和@is2==true?这之前很清楚,但是为什么没有从堆中删除对象?即使我这样做var weak2=new WeakReferencenew TestRefnew Test{Test2=new Test};它还活着!为什么?它没有任何有力的参考。。。
.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 112 (0x70)
    .maxstack 2
    .locals init (
        [0] class Test test,
        [1] class Test test2,
        [2] class [mscorlib]System.WeakReference`1<class TestRef> weak,
        [3] class [mscorlib]System.WeakReference`1<class TestRef> weak2,
        [4] class TestRef tref,
        [5] class TestRef tref2,
        [6] bool is,
        [7] bool is2,
        [8] class Test,
        [9] class TestRef
    )

    IL_0000: nop
    IL_0001: newobj instance void Test::.ctor()
    IL_0006: stloc.s 8
    IL_0008: ldloc.s 8
    IL_000a: ldstr "One"
    IL_000f: callvirt instance void Test::set_Name(string)
    IL_0014: nop
    IL_0015: ldloc.s 8
    IL_0017: stloc.0
    IL_0018: newobj instance void Test::.ctor()
    IL_001d: stloc.s 8
    IL_001f: ldloc.s 8
    IL_0021: ldstr "Two"
    IL_0026: callvirt instance void Test::set_Name(string)
    IL_002b: nop
    IL_002c: ldloc.s 8
    IL_002e: stloc.1
    IL_002f: ldloc.0
    IL_0030: ldloc.1
    IL_0031: newobj instance void TestRef::.ctor(class Test, class Test)
    IL_0036: newobj instance void class [mscorlib]System.WeakReference`1<class TestRef>::.ctor(!0)
    IL_003b: stloc.2
    IL_003c: ldloc.0
    IL_003d: newobj instance void TestRef::.ctor(class Test)
    IL_0042: stloc.s 9
    IL_0044: ldloc.s 9
    IL_0046: ldloc.1
    IL_0047: callvirt instance void TestRef::set_Test2(class Test)
    IL_004c: nop
    IL_004d: ldloc.s 9
    IL_004f: newobj instance void class [mscorlib]System.WeakReference`1<class TestRef>::.ctor(!0)
    IL_0054: stloc.3
    IL_0055: call void [mscorlib]System.GC::Collect()
    IL_005a: nop
    IL_005b: ldloc.2
    IL_005c: ldloca.s tref
    IL_005e: callvirt instance bool class [mscorlib]System.WeakReference`1<class TestRef>::TryGetTarget(!0&)
    IL_0063: stloc.s is
    IL_0065: ldloc.3
    IL_0066: ldloca.s tref2
    IL_0068: callvirt instance bool class [mscorlib]System.WeakReference`1<class TestRef>::TryGetTarget(!0&)
    IL_006d: stloc.s is2
    IL_006f: ret
} // end of method Program::Main
.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 86 (0x56)
    .maxstack 4
    .locals init (
        [0] class Test test2,
        [1] class [mscorlib]System.WeakReference`1<class TestRef> weak,
        [2] class TestRef tref,
        [3] class TestRef tref2
    )

    IL_0000: newobj instance void Test::.ctor()
    IL_0005: dup
    IL_0006: ldstr "One"
    IL_000b: callvirt instance void Test::set_Name(string)
    IL_0010: newobj instance void Test::.ctor()
    IL_0015: dup
    IL_0016: ldstr "Two"
    IL_001b: callvirt instance void Test::set_Name(string)
    IL_0020: stloc.0
    IL_0021: dup
    IL_0022: ldloc.0
    IL_0023: newobj instance void TestRef::.ctor(class Test, class Test)
    IL_0028: newobj instance void class [mscorlib]System.WeakReference`1<class TestRef>::.ctor(!0)
    IL_002d: stloc.1
    IL_002e: newobj instance void TestRef::.ctor(class Test)
    IL_0033: dup
    IL_0034: ldloc.0
    IL_0035: callvirt instance void TestRef::set_Test2(class Test)
    IL_003a: newobj instance void class [mscorlib]System.WeakReference`1<class TestRef>::.ctor(!0)
    IL_003f: call void [mscorlib]System.GC::Collect()
    IL_0044: ldloc.1
    IL_0045: ldloca.s tref
    IL_0047: callvirt instance bool class [mscorlib]System.WeakReference`1<class TestRef>::TryGetTarget(!0&)
    IL_004c: pop
    IL_004d: ldloca.s tref2
    IL_004f: callvirt instance bool class [mscorlib]System.WeakReference`1<class TestRef>::TryGetTarget(!0&)
    IL_0054: pop
    IL_0055: ret
} // end of method Program::Main