临时变量是一回事并且处理得更快吗?

Are temporary variables a thing & do the dispose faster?

我不知道如何正确表达,所以请耐心等待。在 C# .NET 中工作,我继承了一个 class,其中包含一个函数,该函数 returns 是一个非托管函数的对象。当我直接使用继承的函数时,非托管任务失败。如果我创建对继承函数返回的对象的引用并从引用的对象调用非托管函数,它就可以工作。

伪.NET代码示例:

public class A {
  void UnmanagedFunc() {...}
}

public class B {
  public A GetA() {
    return new A();
  }
}

public class C : B {
  public void DoSomething() {
    this.GetA().UnmanagedFunc();
  }
}

public class D : B {
  public void DoSomething() {
    var a = this.GetA();
    a.UnmanagedFunc();
  }
}

您可以看到 class 中的函数 C 和 D 是等效的,但 D 声明了对由基 class 函数实例化的对象的引用。

我的同事说,声明变量可以让非托管进程有时间完成,因为变量的对象仍然需要在直接访问的对象立即释放的地方释放。

这有一定道理,但我觉得这不是一个令人满意的答案。

谁能解释一下这个现象?

如果我对你的问题理解正确,你想知道为什么会这样:

this.GetA().UnmanagedFunc();

失败,而这个:

var a = this.GetA();
a.UnmanagedFunc();

不会。

好吧,让我这样说:至少在非调试构建中,允许编译器和运行时(特别是 JIT 代码生成器)应用优化,您的局部变量 a 可能只是被优化掉,因此出于所有实际目的,您应该假设您的代码的两个版本在功能上是相同的。

在您给出的如此简单的示例中,局部变量只有一个优点:它为您提供了 "name" 或描述 GetA() 返回的对象的方法;例如,您可以调用局部变量 aForFrobblinglastUsedA 或其他名称。

"My collegues say that declaring the variable gives the unmanaged process time to complete because the object of the variable still needs to be disposed where the object that is directly accessed is disposed immediately."

我不接受这种说法,主要是因为您的同事似乎对 .NET 内存管理有一些错误的想法。

  1. 不是变量被释放,而是对象不再被所述变量引用(或任何其他内容,例如字段或参数)。

  2. .NET 中的垃圾收集 (GC) 是不确定的。仅仅因为变量超出范围并不意味着它最后引用的对象会立即被回收。对象(至少是堆上的对象)至少会继续存在到下一次 GC 运行时(无论何时);它们是否被变量/字段/参数引用。导致对象被回收的唯一原因是它不再被任何东西引用;但您不知道 GC 何时启动(除非您明确触发它)。

  3. 术语:.NET 中的 "Disposal" 强烈建议所讨论的对象属于实现 IDisposable 的类型。从您的代码示例来看,这里似乎不是这种情况。

话虽这么说,也许我们没有看到您所有相关的代码。哪里有"disposal"涉及?您的非托管代码是否将 运行 保留在后台(即在单独的线程中)并对 .NET 垃圾收集器无法知道的 .NET 对象执行操作?无论如何,非托管函数 (UnmanagedFunc) 怎么能成为托管对象上的方法呢?许多问题。我觉得除了我上面说的,我不能完全回答你的问题。

只有一件事:如果在处置对象之前确实需要给一些非托管代码一些时间,那么您应该重新考虑程序的设计。明确计时,不要依赖仅在某些时候起作用的技巧(即便如此,您也不知道为什么):非托管代码应该为您提供询问它是否完成的方法;无论是通过回调函数,还是某种事件机制。如果是这样,请确保您的 .NET 对象在此之前不能被垃圾收集器释放,方法是扩展其生命周期范围(例如,通过将对象存储在 class 字段中而不是局部变量中);或查看 System.Runtime.InteropServices.Marshal class.

为您提供的可能性