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


究竟是什么时候发生的 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
        }
    }
}

9290
2018-06-28 17:46


起源

如果你不创建它的实例,你怎么能访问Bar? - BFree
我想他的意思是“做一个例子 富 需要创建“ - Zano


答案:


静态方法与实例方法不同 没有实例 他们所属的类需要被创建才能被调用。当你调用静态方法时,你实际上是使用了 类型的名称 而不是类型的实例 - 这应该强化静态方法不在实例上调用的想法。 这需要重复和强调调用该类的公共静态方法不需要类的实例。

现在,你的例子是畸形的,但据推测, 这条线: if( Foo.SomeCheck() ) 正在呼唤 SomeCheck 使用类型名称的静态方法: Foo  - 不是实例。 但是,必须实例化以便进行此调用  - 但是,在您的示例中,您没有格式良好的实例 Bar。代码通常必须存在于方法(或成员初始化程序)中 - 您在此处没有。

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

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


7
2018-06-28 17:53



对不起,我发现原来的帖子令人困惑。我知道Bar必须被实例化,但是当我们从Bar实例调用SomeCheck时,是否隐式实例化了Foo? - Ian R. O'Brien
总之,没有。您可以在Foo中调用静态方法,而不会实例化任何Foo实例。 - Cylon Cat
我认为应该澄清的是,有一个类的单个“静态实例”的实例化。通常,这完全是隐含的,CLR会为您处理它。但是,可以使用第一次访问类的任何静态成员时执行的静态构造函数。静态构造函数在创建静态实例并将其放置在加载器堆上时执行一次,并可用于自定义类的静态实例的静态状态。有关详细信息,请参阅我的答案中的文章。 - jrista


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

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

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

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


3
2018-06-28 17:58





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

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

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

我希望这有帮助! =)


1
2018-06-28 18:11





这取决于实施 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();
    }
}

0
2018-06-28 17:54





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类。


0
2018-06-28 17:57