在非静态类中调用静态方法时是否实例化了类?

究竟在Bar类中调用Foo.SomeCheck()时会发生什么? 是否为了调用SomeCheck()而创建了一个Foo实例? 如果是这样,这个实例是否存储在堆上,是否通过垃圾收集收集?

public class Foo() { public static bool SomeCheck() { return true; } } public class Bar() { public void SomeMethod() { // what happens when we access Foo to call SomeCheck? if (Foo.SomeCheck()) { //do something } } } 

静态方法与实例方法的不同之处在于, 不需要为它们调用它们所属的类的实例 。 当您调用静态方法时,实际上您使用类型名称而不是类型的实例来进行调用 – 这应该强化静态方法不在实例上调用的想法。 这需要重复和强调不需要类的实例来调用该类的公共静态方法。

现在,您的示例格式不正确,但可能是行: if( Foo.SomeCheck() )使用类型名称调用SomeCheck静态方法: Foo – 而不是实例。 但是,必须实例化以便进行此调用但是,在您的示例中,您没有格式良好的Bar实例。 代码通常必须存在于方法(或成员初始化程序)中 – 您在此处没有。

回答问题的其他部分。 假设有问题的代码是实例方法的一部分,则必须实例化Bar – 并调用该方法。 那些东西必须创建或以其他方式获得Bar的实例。 引用类型将始终在堆上创建 – 但这在很大程度上与此无关。

至于垃圾收集,你通常不应该担心这一点。 .NET运行时确保清除未从程序中的任何根对象引用的实例。 根通常是驻留在callstack上某处的实例,或者由一种或另一种类型的静态成员引用。 由于我们在这里看不到任何创建或引用Bar代码,因此无法确定何时收集它。 例如,如果Bar是单例并存储在静态变量中的某个地方,它可能会存在很长时间 – 也许是程序的整个生命周期。 如果没有看到操纵和管理Bar 所有代码,你就无法真正了解。

我强烈建议您阅读以下文章:

深入了解.NET Framework内部,了解CLR如何创建运行时对象

它解释了.NET运行时如何在低级别工作,并解释了内部细微差别,如Loader Heaps以及静态类/成员的工作方式。 从技术上讲,有静态成员类的“静态实例”的初始实例化。 但是,此启动由运行时以与为类实例处理的方式不同的方式处理。 静态类存储在加载程序堆中,而不是GC管理的。 加载器堆以静态方式分配和增长,并且不会被压缩。 这篇文章很精彩,应该让您对CLR的运作方式有所了解。

(注意:我不确定本文对.NET 4的有效性。我知道.NET 4中有GC更改,但我不确定有多少基本的运行时更改.DLR的引入和其他function可能会在某种程度上偏离上述文章中的解释。)

Foo不需要实例化,也不会根据结果在SomeCheck静态方法调用上立即获得,您将获得方法本身返回的值,而不是类的实例。

请查看这些参考资料以获取更多详细信息:

  1. 静态与非静态方法 ;
  2. 静态类和静态类成员(C#编程指南) 。

我希望这有帮助! =)

这取决于SomeMethod的实现。 必须从某个地方调用该方法,可能是一个“驱动程序”类,它将实例化Bar并调用SomeMethod 。 例如:

 public class Driver { public static void Main() { Bar bar = new Bar(); bar.SomeMethod(); } } 

鉴于你当前对SomeMethod实现,是的,你必须实例化它。

但是,只要SomeMethod只调用另一个静态方法,我们就可以将设为静态。 在这种情况下,您不必创建Bar实例来调用该方法。 即

 public class Driver { public static void Main() { Bar.SomeMethod(); } } 
 public class Manipulate { public static int Main(string[] args) { Bar bar = new Bar(); bar.BarFoo(); Console.ReadKey(); return 0; } } public class Foo { public static bool SomeCheck() { return true; } } public class Bar { // what happens when we access Foo to call SomeCheck? public void BarFoo() { if (Foo.SomeCheck()) { Console.WriteLine("Hello am true"); } } } 

是的,你需要创建一个Bar实例,但不是Foo类,因为它是一个静态metod。 唯一不同的是,静态方法在类级别(编译时)而不是对象级别(运行时)调用,因此您不需要实例化Foo类。