究竟是什么时候发生的 Foo.SomeCheck() 被称为 酒吧 类?是一个实例 富 为了打电话而创建 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
}
}
}
静态方法与实例方法不同 没有实例 他们所属的类需要被创建才能被调用。当你调用静态方法时,你实际上是使用了 类型的名称 而不是类型的实例 - 这应该强化静态方法不在实例上调用的想法。 这需要重复和强调: 调用该类的公共静态方法不需要类的实例。
现在,你的例子是畸形的,但据推测, 这条线: 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的引入和其他功能可能会在某种程度上偏离上述文章中的解释。)
Foo
不需要实例化,也不会立即实现 SomeCheck
根据结果调用静态方法,您将获得方法本身返回的值,而不是类的实例。
请查看这些参考资料以获取更多详细信息:
- 静态与非静态方法;
- 静态类和静态类成员(C#编程指南)。
我希望这有帮助! =)
这取决于实施 SomeMethod
。必须从某个地方调用该方法,可能是一个“驱动程序”类,它将实例化Bar和call SomeMethod
。例如:
public class Driver
{
public static void Main()
{
Bar bar = new Bar();
bar.SomeMethod();
}
}
鉴于您目前的实施情况 SomeMethod
是的,你必须实例化它。
但是,只要 SomeMethod
只调用另一个静态方法,我们可以make 它 静也是。在这种情况下,您不必创建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类。