在C#中将引用设置为null

4

我已经很长时间在寻找这些信息了。以前从来没有看到有人问过这样的问题。 我知道我们可以在C#的不安全代码内使用指针,但这不是现在的情况。 问题是:

MyClass beta = new MyClass();
MyClass alpha = beta;
beta = null;

现在我需要将beta设置为null,同时也要将alpha设置为null。 假设我已经在函数中返回了alpha,所以我无法再访问它了,那么我该如何将其设置为null? 如果beta和alpha是指针类型的话,在c++中我可以释放beta指向的内存,但是我不知道在c#中该怎么做。
更简单地说,假设我必须将这两个变量都设置为null,但我只能访问其中一个。
编辑
我看到了一些与我的问题无关的答案...我会尝试再解释一遍。 我正在创建一个类,用于执行某些运动效果并返回一个实例,该实例可用于暂停或停止此运动。 使用此类的程序员习惯于在使用变量之前进行 if(variable != null) 的测试。 我需要的是当运动结束时,他们拥有的实例被转换为null,这样他们就知道它已经没有用处了。
有什么办法可以做到这一点吗?

3
不需要手动"释放"它,垃圾收集器会替你完成这项工作。 - DaveShaw
2
我对此的第一个问题是为什么?正如@DaveShaw上面所说,垃圾收集器会替你完成这个任务。 - Brian
重点在于另一个变量无法访问底层对象,即使该变量尚未超出范围。 - Servy
什么?我猜你还不习惯托管代码。一旦这些引用超出范围并且不再需要,它们将被垃圾回收。 - Federico Berasategui
@HighCore 我猜你对非托管代码不够熟悉,无法理解他比喻的含义,并且错误地认为他误解了托管代码。 - Servy
发布您遇到问题的实际代码可能会有所帮助。 - Joanna Derks
4个回答

10

你需要增加一层额外的间接性,如果换成C++术语,MyClass是一个对象指针,因此要将两个指针都设置为null,你需要传递指向指针的指针,以便你可以将指针解析为指针,将其设置为null,则双重指针将解析为 null

在C#中增加一层额外的间接性通常意味着创建一个新的类。

public class Wrapper<T>
{
    public T Value { get; set; }
}

使用这种方法,我们可以创建Wrapper<MyClass>对象,使得alphabeta都是这个Wrapper的实例(确保它们都指向同一个实例),如果要同时影响这两个“指针”,只需将WrapperValue设置为null即可。


+1,这是一个好的方法,而且它不会像在C++中通过陈旧指针访问已删除对象时那样匹配AV/未定义行为 :) - Alexei Levenkov
正如我在第一段中所述,C++中适当的类比是使用双指针或指向指针的引用(如果需要从“外部”作用域而不是内部作用域访问变量,则在C#中也可以选择这种方式)。在C++中,这就是我解决这个问题的方法(以避免访问已删除对象时出现的问题)。 - Servy
是的,但指向指针的指针并不是 OP 问题中所建议的期望 C++ 行为(或者至少是我理解的方式:“在 C++ 中,如果 beta 和 alpha 是指针,我可以只释放 beta 指向的内存”)。 - Alexei Levenkov
在C#中,对象永远不会像在C++中那样超出范围。当它们不再使用时,它们会被垃圾回收器自动处理。这比C++更复杂,因为变量的作用域完全是确定性的。CLR垃圾回收器会主动遍历所有已创建的对象,并计算它们是否正在使用。 - Mustafa Ekici
1
@MustafaEkici 这与问题无关。很遗憾,您过于字面理解 OP 的比喻,并未考虑他真正想表达的意思,而只是关注他的措辞。这个问题的答案与垃圾回收器、对象的收集或 IDisposable 没有任何关系。 (好吧,如果由于编辑限制而无法实现我提供的答案,则 IDisposable 是可能的 hack。)哦,顺便说一句,变量确实具有作用域,但是这些变量引用的对象可能没有。 - Servy
显示剩余3条评论

0
如果您需要获取某种AV /异常(以匹配C ++访问已删除对象的行为),那么最接近的方法是使对象IDisposable,并使所有方法/属性在对象被处理后抛出异常(类似于Stream派生对象的行为)。
MyClass beta = new MyClass();
MyClass alpha = beta;
beta.Dispose();

alpha.Method(); // should throw  ObjectDisposedException.

0

除非您的类包含可处理对象,否则不需要处理该对象,将其设置为null只会使对象为空,这不会释放内存,但如果您稍后需要检查对象,则会有所帮助...

如果您的类需要标记为可处理的,因为它需要清理其内存使用,请考虑让您的类继承IDisposable!接口。


0

你不需要手动管理内存。C# 内存是自动管理的,因此当没有更多引用时,对象会被释放。如果你特别想要释放某些东西,因为你捕获了 OutOfMemoryException 异常,那么是的,你可以像 @JanesAbouChleih 所指出的那样开始将一些东西设置为 null 并强制垃圾回收。更好的方法是调用 .Dispose 方法并实现任何其他清理代码 MyClass 可能需要的(关闭文件、刷新缓冲区等)。

一些参考资料:

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

http://msdn.microsoft.com/en-us/library/ms973837.aspx

此外,关于如何/何时/为什么处理对象的类似问题:您需要处理对象并将其设置为null吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接