猿问
回到首页
个人中心
反馈问题
注册登录
下载APP
首页
课程
实战
体系课
手记
专栏
慕课教程
您需要释放对象并将其设置为空吗?
您需要释放对象并将其设置为空吗?
您需要释放对象并将其设置为NULL吗?或者垃圾收集器会在它们超出作用域时清除它们吗?
杨魅力
浏览 497
回答 3
3回答
小唯快跑啊
对象在C#中从不超出作用域,就像它们在C+中所做的那样。当垃圾收集器不再使用时,垃圾收集器会自动处理它们。这是一种比C+更复杂的方法,在C+中,变量的范围完全是确定性的。CLR垃圾收集器主动遍历所有已创建的对象,并计算出它们是否被使用。对象可以在一个函数中“超出作用域”,但如果返回其值,则GC将检查调用函数是否保留返回值。将对象引用设置为null没有必要,因为垃圾收集是通过计算其他对象引用的对象来完成的。在实践中,你不必担心破坏,它只是起作用了,而且很棒:)Dispose必须对实现的所有对象调用IDisposable当你和他们一起工作完之后。通常您会使用using用这样的对象阻止:using (var ms = new MemoryStream()) { //...}编辑在可变范围内。Craig询问变量范围是否对象生存期有任何影响。为了正确地解释CLR的这个方面,我需要从C+和C#中解释一些概念。实际变量范围在这两种语言中,变量只能在定义的相同范围内使用-类、函数或用大括号括起来的语句块。然而,不同之处在于,在C#中,不能在嵌套块中重新定义变量。在C+中,这是完全合法的:int iVal = 8;//iVal == 8if (iVal == 8){ int iVal = 5; //iVal == 5}//iVal == 8但是,在C#中,您会得到一个编译器错误:int iVal = 8;if(iVal == 8) { int iVal = 5; //error CS0136: A local variable named 'iVal' cannot be declared in this scope because it would give a different meaning to 'iVal', which is already used in a 'parent or current' scope to denote something else}如果您查看生成的msil-函数使用的所有变量都是在函数的开头定义的,这是有意义的。看看这个函数:public static void Scope() { int iVal = 8; if(iVal == 8) { int iVal2 = 5; }}下面是生成的IL。注意,在if块中定义的iVal2实际上是在函数级别定义的。这实际上意味着,就变量生存期而言,C#只具有类和函数级别的作用域。.method public hidebysig static void Scope() cil managed{ // Code size 19 (0x13) .maxstack 2 .locals init ([0] int32 iVal, [1] int32 iVal2, [2] bool CS$4$0000)//Function IL - omitted} // end of method Test2::ScopeC+作用域和对象生存期每当在堆栈上分配的C+变量超出作用域时,它就会被销毁。请记住,在C+中,您可以在堆栈或堆上创建对象。当您在堆栈上创建它们时,一旦执行离开范围,它们就会从堆栈中弹出并被销毁。if (true) { MyClass stackObj; //created on the stack MyClass heapObj = new MyClass(); //created on the heap obj.doSomething();} //<-- stackObj is destroyed//heapObj still lives当在堆上创建C+对象时,必须显式销毁它们,否则就是内存泄漏。但是,堆栈变量没有这样的问题。C#对象生命周期在CLR中,对象(即引用类型)是总在托管堆上创建。对象创建语法进一步加强了这一点。考虑一下这个代码片段。MyClass stackObj;在C+中,这将创建一个MyClass并调用其默认构造函数。在C#中,它将创建对类的引用MyClass这并不意味着什么。创建类实例的唯一方法是使用new操作员:MyClass stackObj = new MyClass();在某种程度上,C#对象非常类似于使用newC+中的语法-它们是在堆上创建的,但与C+对象不同,它们是由运行时管理的,因此您不必担心对它们进行析构。因为对象是总在堆中,对象引用(即指针)超出作用域的事实变得毫无意义。在确定是否要收集对象时,涉及的因素比简单地存在对象的引用所涉及的因素更多。C#对象引用乔恩·斯基特Java中的对象引用比较连接到气球上的字符串,气球是对象。同样的类比也适用于C#对象引用。它们只是指向包含对象的堆的位置。因此,将其设置为NULL对象生存期没有直接影响,气球继续存在,直到GC“弹出”它。按照气球的类比,一旦气球没有附加条件,它就可以被摧毁,这似乎是合乎逻辑的。事实上,这正是引用计数对象在非托管语言中的工作方式。但是,这种方法对循环引用没有很好的效果。想象一下,两个气球由一根绳子连接在一起,但没有一个气球与任何其他气球相连。在简单的参考计数规则下,它们都继续存在,即使整个气球组是“孤儿”。NET对象很像屋顶下的氦气气球。当屋顶打开(GC运行)NETGC使用分代GC和标记和扫描的组合。分代方法包括运行时倾向于检查最近分配的对象,因为它们更可能未使用;标记和扫描涉及运行时遍历整个对象图,并计算出是否有未使用的对象组。这充分地处理了循环依赖问题。此外,.NET GC在另一个线程上运行(即所谓的终结器线程),因为它有相当多的工作要做,在主线程上这样做会中断程序。
0
0
0
临摹微笑
就像其他人说的,你绝对想打电话给Dispose如果类实现IDisposable..我对此采取了相当强硬的立场。有些人可能会声称Dispose在……上面DataSet例如,因为他们拆掉了它,看到它没有做任何有意义的事情,所以是毫无意义的。但是,我认为这个论点中有很多谬误。朗读,阅读这,这个值得尊敬的人就这个问题进行有趣的辩论。那就读读我的推理这里为什么我认为杰弗里·里克特在错误的阵营。现在,关于是否应该将引用设置为null..答案是否定的。让我用下面的代码来说明我的观点。public static void Main(){ Object a = new Object(); Console.WriteLine("object created"); DoSomething(a); Console.WriteLine("object used"); a = null; Console.WriteLine("reference set to null");}那么你认为什么时候被引用的对象a是否有资格领取?如果你说打完电话a = null那你就错了。如果你说在Main方法完成,那么您也错了。正确的答案是,它有时有资格领取。期间打电话给DoSomething..这是对的。它有资格以前引用设置为null甚至在呼吁DoSomething完成。这是因为即使对象引用仍然是根,JIT编译器也可以识别对象引用何时不再取消引用。
0
0
0
打开App,查看更多内容
随时随地看视频
慕课网APP
相关分类
C#
typedef入门问题
1 回答
.NET
.net 中 字符串含有超链接,如何给超链接自动加上a标签?
1 回答
请问.net 中用jquery传值安全吗?
2 回答
继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续