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

时间:2010-06-28 17:46:59

标签: c# oop class static methods

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
        }
    }
}

5 个答案:

答案 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静态方法调用立即获得,您将获得方法本身返回的值,而不是实例上课。

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

  1. Static vs Non-Static Methods;
  2. Static Classes and Static Class Members (C# Programming Guide)
  3. 我希望这会有所帮助! =)

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