在 Bar 类中调用 Foo.SomeCheck()时究竟会发生什么?是否创建 Foo 的实例才能调用 SomeCheck()?如果是这样,这个实例是否存储在堆上,是否通过垃圾收集进行收集?
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
}
}
}
答案 0 :(得分:7)
静态方法与实例方法的不同之处在于,需要创建它们所属类的 no instance 才能调用它们。当您调用静态方法时,实际上您使用类型的名称而不是类型的实例来进行调用 - 这应该强化静态方法不会在实例上调用的想法。 重复和强调:调用该类的公共静态方法不需要类的实例。
现在,您的示例格式错误,但可能行:if( Foo.SomeCheck() )
使用类型名称调用SomeCheck
静态方法:Foo
- 不是实例。 然而,必须实例化才能进行此调用 - 但是,在您的示例中,您没有格式良好的 Bar
实例。代码通常必须存在于方法(或成员初始化程序)中 - 您在此处没有。
回复问题的其他部分。假设有问题的代码是实例方法的一部分,则必须实例化Bar
- 并调用该方法。那些某些东西必须创建或以其他方式获取Bar
的实例。引用类型将始终在堆上创建 - 但这在很大程度上与此无关。
至于垃圾收集,你通常不应该担心这一点。 .NET运行时确保清除未从程序中的任何根对象引用的实例。根通常是驻留在callstack上某处的实例,或者由一种或另一种类型的静态成员引用。由于我们在此处未看到任何创建或引用Bar
的代码,因此无法在时收集。例如,如果Bar
是单例并存储在静态变量中的某个地方,它可能会存在很长时间 - 也许是程序的整个生命周期。如果没有看到操作和管理Bar
的所有代码,你就无法真正知道。
答案 1 :(得分:3)
我强烈建议您阅读以下文章:
Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects
它解释了.NET运行时如何在低级别工作,并解释了内部细微差别,如Loader Heaps以及静态类/成员的工作方式。从技术上讲,有静态成员类的“静态实例”的初始实例化。但是,此启动由运行时以与为类实例处理的方式不同的方式处理。静态类存储在加载程序堆中,而不是GC管理的。加载器堆以静态方式分配和增长,并且不会被压缩。这篇文章非常精彩,应该让您对CLR的运作方式有所了解。
(注意:我不确定本文对于.NET 4的有效性。我知道.NET 4中有GC更改,但我不确定有多少基本的运行时更改。 DLR和其他功能可能在某种程度上偏离了上述文章中的解释。)
答案 2 :(得分:1)
Foo
不需要实例化,也不会根据结果SomeCheck
静态方法调用立即获得,您将获得方法本身返回的值,而不是实例上课。
请查看这些参考资料以获取更多详细信息:
答案 3 :(得分:0)
这取决于SomeMethod
的实施。必须从某个地方调用该方法,可能是一个“驱动程序”类,它将实例化Bar并调用SomeMethod
。例如:
public class Driver
{
public static void Main()
{
Bar bar = new Bar();
bar.SomeMethod();
}
}
鉴于您当前的SomeMethod
实施,是的,您必须实例化它。
但是,只要SomeMethod
仅调用另一个静态方法,我们就可以将make it 设为静态。在这种情况下,您不必创建Bar实例来调用该方法。即。
public class Driver
{
public static void Main()
{
Bar.SomeMethod();
}
}
答案 4 :(得分:0)
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类。