C# 将对象指定给其他对象是否会创建副本?

C# 将对象指定给其他对象是否会创建副本?,c#,object,reference,garbage-collection,dispose,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 smallcla

我尝试了下面的代码,得到了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();
}
更新: 我期望在p.fun1()中释放引用的内存时出现对象引用异常

不,assinging不是一个“新”语句,它复制了。。。。作为引用,它不会创建新对象。一节课

对于结构,它是这样做的


我建议通过阅读文档或一本书来学习C#-这些基本知识通常在这些文档或书中被非常详细地处理。

下面是一个简单的例子,说明如何使用assinging

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
        }
    }
}
就像你看到的

  • 首先,我们创建两个对象
    objA
    objB

    我们显示的值与预期值相同,它们都是0

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

  • 现在我们正在分配
    objA
    objB
    因此,
    objB
    的值也得到了1000

  • 如果我们现在将
    objA
    的值更改为1055
    objB
    的值也会更改 因为objB不再是一个单独的对象,所以它现在保持不变 类似于objA的引用

  • 编辑 现在我将向你们展示如何根据你们的例子得到你们的错误

    将您的
    aaaaa等级
    更改为:

    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)
        {
            Program p = new Program();
            p.fun1();
            GC.Collect();
            p.fun2();
    
            Console.Read();
        }
    
    好的,让我们完成这些变化

    我们正在使用(您也可以使用) 如果GC现在遇到我们的对象,他无法找到StrongReference,因此可以收集它

    现在,您需要调用它,因为它迫使GC执行其工作(此时此刻)


    请记住,正如我之前告诉您的,在GC销毁对象(AFAIK)之前,它将从GC中被调用,因此在销毁对象之前,有地方可以放置所有需要执行的操作

    我已将dispose函数中的GC.SuppressFinalize替换为GC.Collect(),但这并不能释放内存。。结果我收到了1000英镑

    我猜,由于它包含其他引用(变量h),即使我们显式调用它,GC也不会释放内存

    因此,无论分配的(新)对象是否超出范围,我们都可以很好地传递和分配对象


    如果我错了,请纠正我

    如果您想到每一个引用类型变量、字段、参数、数组插槽或其他此类存储位置都有“null”或“object#24601”[或其他数字],您就不会犯太大的错误。实际上,只有少数几件事可以通过引用来完成:

  • 您可以创建空引用

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

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

  • 您可以检查两个引用是否彼此相等,或者其中一个是否等于null

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

  • 如果
    myCar
    是某个引用类型的变量,则类似
    myCar.Color=CarColors.Blue的语句根本不会影响变量
    myCar
    。相反,它将观察到
    myCar
    持有[例如]“Object#8675309”,然后要求系统访问Object#8675309的
    Color
    属性或字段。相反,如果
    otherCar
    恰好持有“object#90210”,则形式为
    otherCar=myCar
    的语句不会对object#8675309或object#90210做任何处理,而是将存储在
    otherCar
    中的“90210”替换为“8675309”


    只要存在对对象的任何形式的引用,就可以保证对象存在,但是如果有两个对象,虽然相互引用,但不被宇宙中的任何其他对象引用,那么这两个对象可能同时停止存在。这条规则是绝对的,但也有一些曲折:代码可能会向对象请求
    WeakReference
    ;只要存在对某个对象的弱引用,就可以保证该对象存在,但如果系统发现不存在对该对象的强引用,它将使对该对象的每个
    WeakReference
    无效。此外,系统保留了一个列表,其中列出了在放弃时希望得到通知的所有对象。如果系统发现此列表包含对某个对象的唯一引用,则会将该对象移动到一个强烈引用的对象列表中,该列表中的
    Finalize
    方法应在第一个方便的时机运行。当对象的
    Finalize
    方法运行时,引用将从后面的列表中删除。如果同时未在任何位置存储对该对象的引用,则该对象将不再存在。

    您的预期输出是什么?当你不说出你的想法时,很难判断你的想法哪里错了。代码运行良好:预期输出为
    1000
    。问题不太清楚。输出1000是预期值。可能是告诉您期望的输出有助于解释。我期望输出为异常。因为赋值h=d,必须复制对象的引用,而不是对象的内存。考虑到这一点,它只是共享引用,并且由于对象是在p.fun1()中处理的,因此结果如何变成1000是一个问题。您没有处理任何内存。您不明白
    IDisposable
    Dispose
    是如何工作的。当您在垃圾收集器中清理对象时,您的
    Dispose
    方法仅将该对象标记为不调用终结器(这就是它的作用)。它根本不会释放任何内存。@MuthukumarPalaniappan请尝试一本关于C#basics的书。不,没有办法释放对象。你可以强制垃圾收集,但这会产生严重的副作用。看看我的,如果你这样做,你会得到你所期望的好结果
        static void Main(string[] args)
        {
            Program p = new Program();
            p.fun1();
            GC.Collect();
            p.fun2();
    
            Console.Read();
        }