将一个对象分配给其他对象是否会创建一个副本?

Mut*_*pan 5 c# garbage-collection dispose reference object

我尝试使用下面的代码,得到的输出为 1000。我听说分配对象必须共享引用,而不是复制整个对象内存。这里的结果是不同的。任何人都可以帮忙吗?

public aaaaa ad = new aaaaa();

static void Main(string[] args)
{
    Program p = new Program();
    p.fun1();
    p.fun2();
}

public void fun1()
{
    using(smallclass s = new smallclass())
    {
        s.j = 1000;
        ad.fun1(s);
    }
}

public void fun2()
{
    ad.fun2();
}
Run Code Online (Sandbox Code Playgroud)
public class aaaaa
{
    public smallclass h = new smallclass();
    public void fun1(smallclass d)
    {
        h = d;
    }
    public void fun2()
    {
        Console.WriteLine(h.j);
    }
}

public class smallclass:IDisposable
{
    public int j = 9;

    public void Dispose()
    {
        GC.SuppressFinalize(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我预计会出现对象引用异常,因为引用的内存已在 p.fun1(); 中处置;

Wii*_*axx 2

这是一个简单的例子,分配是如何工作的

using System;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static smallclass objA = new smallclass();
        private static smallclass objB = new smallclass();

        private static void Main(string[] args)
        {
            showValues();

            objA.value = 1000;

            showValues();

            objB = objA;

            showValues();

            objA.value = 1055;

            showValues();
        }

        private static void showValues()
        {
            Console.WriteLine("objA.value: " + objA.value);
            Console.WriteLine("objB.value: " + objB.value);

            Console.ReadLine();
        }
    }

    internal class smallclass : IDisposable
    {
        public int value = 0;

        public void Dispose()
        {
            //Here you can remove eventHandlers
            //or do some other stuff before the GC will play with it
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

就像你可以看到的

  1. 首先我们创建 2 个对象objAobjB
    然后我们显示预期的值,它们都是 0

  2. 之后我们将 的值增加到objA1000,a 的值为objA1000,并且 的值objB保持为 0

  3. 现在我们进行分配objAobjB 因此值objB也为 1000

  4. 如果我们现在将 的值更改objA为 1055,则objBget 的值也会更改,因为objB它不再是一个单独的对象,它现在像以前一样拥有相同的objA引用

编辑

现在我将向您展示如何根据您的示例获得错误

将你的更改aaaaa class为:

public class aaaaa
{
    public WeakReference<smallclass> h;
    public void fun1(smallclass d)
    {
        h = new WeakReference<smallclass>(d);
    }
    public void fun2()
    {
        smallclass k;
        if(h.TryGetTarget(out k))
        Console.WriteLine(k.j);
        else
            Console.WriteLine("ERROR ERRROR ERROR");
    }
}
Run Code Online (Sandbox Code Playgroud)

并将您的修改static void Main(string[] args)为:

    static void Main(string[] args)
    {
        Program p = new Program();
        p.fun1();
        GC.Collect();
        p.fun2();

        Console.Read();
    }
Run Code Online (Sandbox Code Playgroud)

好的,让我们完成这些更改

我们正在使用(您也可以使用Wea​​kReference 如果 GC 现在遇到我们的对象,他找不到 StrongReference 所以可以收集它WeakReference<T>

现在GC.Collect()你需要调用它,因为它迫使 GC 完成他的工作(现在此时此刻)

请记住,就像我之前告诉过你的那样,IDisposable会在销毁对象之前从 GC 中调用(AFAIK),因此有一个地方可以放置在对象被销毁之前需要完成的所有内容