【问题标题】:Set a reference to null in c#在 C# 中设置对 null 的引用
【发布时间】:2012-12-31 07:14:06
【问题描述】:

我寻找这个信息已经很久了。从来没见过有人问这样的问题。 我知道我们可以在不安全代码中使用 C# 中的指针,但事实并非如此。 问题是:

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

我现在需要做的是将 beta 设置为 null 并将 alpha 设置为 null。 假设我在一个函数中返回了 alpha,所以我无法再访问它,那么,如何将它设置为 null? 在 c++ 中,如果 beta 和 alpha 是指针,我可以释放 beta 指向的内存,但我不知道在 c# 中这样做的方法。

以更基本的方式,假设我必须将两个变量都设置为 null,但我只能访问其中一个。


编辑

我确实看到了一些与我所做的问题无关的答案......我会再次尝试解释。 我正在创建一个做一些运动效果的类,并返回一个可用于暂停或停止此运动的实例。 使用这个类的程序员习惯在使用它之前用 if(variable != null) 测试变量。 我需要的是,当运动结束时,他们拥有的实例变为空,所以他们知道它不再有用了。

有什么办法吗?

【问题讨论】:

  • 您不需要“释放”它,垃圾收集器会为您完成。
  • 我对你的第一个问题是为什么?正如上面@DaveShaw 所说,垃圾收集器会为您完成。
  • 重点是让其他变量无法访问底层对象,即使该变量没有超出范围。
  • 什么??我猜你不习惯托管代码。一旦超出范围并且不再需要这些引用,它们将被垃圾回收
  • @HighCore 我猜你只是对非托管代码不够熟悉,无法理解他的类比的含义,并且错误地假设他误解了托管代码。

标签: c# pointers memory-management


【解决方案1】:

您需要添加一个额外的间接层。用 C++ 术语来说,MyClass 是一个指向对象的指针,因此要将两个指针都设置为 null,您需要传递指向指针的指针,以便您可以将指向指针的指针解析为指针,设置将其设为 null,并且两个双指针都将解析为 null

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

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

使用它,我们可以使alphabeta 成为Wrapper&lt;MyClass&gt; 对象(确保它们都是Wrapper 的同一个实例),并且要影响两个“指针”,您只需设置@987654328 @ 的Wrappernull

【讨论】:

  • +1,这里肯定缺少泛型。我希望您的答案中有一些带有递归代表的 lambda。
  • +1,这是一个很好的方法,它也不匹配 C++ AV/未定义的行为通过过时的指针访问已删除的对象:)
  • @AlexeiLevenkov 正如我在第一段中所说,C++ 中适当的类比是有一个双指针,或对指针的引用(如果需要,这将是 C# 中的一个选项从“外部”范围访问变量,而不是内部范围)。在 C++ 中,这就是我解决这个问题的方法(以避免上述访问已删除对象的问题)。
  • 是的,但是指针指向指针并不是 OP 的问题中所建议的作为所需的 C++ 行为(或者至少我如何阅读它:“在 C++ 中,如果 beta 和 alpha 是指针,我可以只是释放 beta 指向的内存”)
  • @MustafaEkici 这与手头的问题无关。不幸的是,你太从字面上理解了 OP 的类比,没有考虑他真正想说的是什么,而不是他怎么说的。这个问题的答案与垃圾收集器、对象收集或IDisposable 无关。 (好吧,IDisposable 是一个可能的 hack,如果我提供的答案由于可以编辑的限制而无法实现。)哦,为了记录,变量确实有范围,它是那些变量引用的对象那可能不会。
【解决方案2】:

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

如果你的类需要被标记为一次性的,因为它需要清理它的内存使用,请考虑让你的类继承自IDisposable!界面。

【讨论】:

    【解决方案3】:

    如果您需要获得某种 AV/异常(以匹配访问已删除对象的 C++ 行为),您可以获得的最接近的方法是使对象 IDisposable 并在对象被释放后抛出所有方法/属性(类似于 Stream -派生对象的行为)。

    MyClass beta = new MyClass();
    MyClass alpha = beta;
    beta.Dispose();
    
    alpha.Method(); // should throw  ObjectDisposedException.
    

    【讨论】:

      【解决方案4】:

      您也不需要这样做。 C# 内存是自动管理的,因此当不再有对它们的引用时,它们就会被释放。如果您因为捕获 OutOfMemoryException 而特别想要释放某些东西,那么是的,您可以开始将其设置为 null 并强制垃圾收集器,正如 @JanesAbouChleih 指出的那样。最好调用.Dispose 方法并实现MyClass 可能需要的任何其他清理代码(关闭文件、刷新缓冲区等)。

      一些参考资料:

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

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

      另外,关于如何/何时/为什么处置物品的类似问题:Do you need to dispose of objects and set them to null?

      【讨论】:

        猜你喜欢
        • 2011-06-05
        • 2012-10-18
        • 1970-01-01
        • 2018-11-05
        • 2011-05-21
        • 2016-12-25
        • 2011-06-24
        • 1970-01-01
        • 2016-07-08
        相关资源
        最近更新 更多