临时变量是一个东西吗?处理更快?

时间:2015-04-24 12:35:06

标签: c# variables memory

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

伪.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();
  }
}

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

我的同事说声明变量会让非托管进程有时间完成,因为变量的对象仍然需要处理直接访问对象的位置。

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

任何人都可以解释这种现象吗?

1 个答案:

答案 0 :(得分:4)

如果我理解你的问题,你想知道为什么:

this.GetA().UnmanagedFunc();

失败了,而这个:

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

没有。

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

在你给出的这么简单的例子中,局部变量只有一个优点:它为你提供了“命名”或描述GetA()返回的对象的方法;例如,您可以调用局部变量aForFrobblinglastUsedA或其他任何内容。

  

“我的同事说声明变量会让非托管的处理时间完成,因为变量的对象仍然需要处理直接访问的对象所在的位置。”

我不接受这个论点,主要是因为看起来你的同事对.NET内存管理有一些错误的想法。

  1. 不是变量被处置,而是对象不再被所述变量(或其他任何东西,如字段或参数)引用。

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

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

  4. 话虽如此,也许我们看不到所有相关的代码。哪里有“处置”?您的非托管代码是否继续在后台运行(即在单独的线程中)并对.NET垃圾收集器无法了解的.NET对象执行操作?无论如何,非托管函数(UnmanagedFunc)如何成为托管对象的方法?许多问题。除了我上面所说的,我觉得我无法完全回答你的问题。

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