将对象分配给其他对象会创建副本吗?

时间:2014-02-14 06:01:55

标签: c# object reference garbage-collection dispose

我尝试使用下面的代码,我得到输出为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();
}
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);
    }
}

更新:    我期待一个对象引用异常,因为引用的内存放在p.fun1();

4 个答案:

答案 0 :(得分:2)

不,assingning不是一个“新”语句,它复制....一个引用,它不会创建一个新对象。对于一个班级。

对于结构体,它会这样做。

我建议通过阅读文档或书籍来学习C# - 这些基础知识通常会在这些基础知识中得到很好的处理。

答案 1 :(得分: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
        }
    }
}

就像你看到的那样

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

  2. 之后我们将objA的值增加到1000 objA a的值为1000,objB的值保持为0

  3. 现在我们正在协助objAobjB 所以objB的值也得到了1000

  4. 如果我们现在将objA的值更改为1055 objB的值也变了 因为objB不再是一个单独的对象,它现在保持不变 像objA这样的引用

  5. 修改

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

    将您的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");
        }
    }
    

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

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

    好的,让我们完成修改

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

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

    并且记得就像我之前告诉你的那样IDisposable会在他破坏对象(AFAIK)之前从GC调用它,所以在对象被破坏之前有地方可以放置所有需要完成的东西

答案 2 :(得分:1)

如果你想到每个引用类型变量,字段,参数,数组插槽或其他此类存储位置,持有“null”或“object#24601”[或其他一些数字],你就不会出错。实际上只有少数事情可以用引用来完成:

  1. 您可以创建空引用

  2. 您可以要求系统创建一个新对象并返回对它的引用

  3. 您可以将一个引用复制到另一个

  4. 您可以检查两个引用是否彼此相等,或者一个引用是否等于null。

  5. 您可以要求系统对引用标识的对象执行某些操作

  6. 如果myCar是某个引用类型的变量,则myCar.Color = CarColors.Blue之类的语句根本不会影响变量myCar。相反,它会观察到myCar持有[例如]“对象#8675309”,然后要求系统访问对象#8675309的Color属性或字段。相反,如果otherCar碰巧持有“对象#90210”,则otherCar=myCar形式的语句将不会对对象#8675309执行任何操作,也不对对象#90210执行任何操作,而是替换“90210”存储在otherCar中,带有“8675309”。

    对象保证存在,只要存在任何形式的引用,但是如果有两个对象虽然彼此引用,但未被引用通过宇宙中的任何其他东西,两个对象可能同时不复存在。这条规则是绝对的,但有一些曲折:代码可能会向对象请求WeakReference;只要存在对它的弱引用,就保证存在一个对象,但是如果系统发现没有对某个对象的强引用,它将使每个WeakReference无效。此外,系统保留所有想要在被放弃时通知的对象的列表。如果系统发现此列表包含对象的唯一引用,则它会将对象移动到强引用的对象列表,其Finalize方法应在第一个方便的机会运行。运行对象的Finalize方法时,将从后一个列表中删除引用。如果在同一时间内没有对对象的引用存储,该对象将不再存在。

答案 3 :(得分:0)

我已经在dispose函数中用GC.Collect()替换了GC.SuppressFinalize,但这并没有释放内存..并且结果是收到1000。

我猜,因为它拥有其他引用(变量h),即使我们显式调用它,GC也不会释放内存。

因此,我们可以很好地传递和分配对象,而不管分配的(新)对象是否超出范围。

如果我错了,请纠正我。