Is a class instantiated when a static method is ca

2019-04-20 20:28发布

问题:

Exactly what happens when Foo.SomeCheck() is called in the Bar class? Is an instance of Foo created in order to call SomeCheck()? If so, is this instance stored on the heap, and is it ever collected through garbage collection?

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

回答1:

Static methods differ from instance methods in that no instance of the class they belong to needs to have been created for them to be called. When you call a static method, you in fact make the call using the name of the type rather than an instance of the type - which should reinforce the idea that static methods are not called on instances. That bears repeating and emphasis: No instance of a class is required to call a public static method of that class.

Now, your example is malformed, but presumably, the line: if( Foo.SomeCheck() ) is calling the SomeCheck static method using the name of the type: Foo - not an instance. Bar however, has to be instantiated in order to make this call - however, in your example, you don't have a well-formed instance of Bar. Code generally has to exist inside a method (or a member initializer) - which you don't have here.

To respond to the other parts of your question. Assuming the code in question is part of an instance method, something has to instantiate Bar - and invoke that method. That something would have to create or otherwise acquire an instance of Bar. Reference types will always be creted on the heap - but that's largely irrelevant here.

As for garbage collection, you normally shouldn't worry about this. The .NET runtime makes sure to cleanup instances that are not referenced from any root object in your program. Roots are typically instances that reside somewhere on the callstack or are referenced by static members of one type or another. Since we don't see any code here that creates or references Bar it's impossible to say when it will be collected. For instance, if Bar is a singleton and stored somewhere in a static variable, it may live for a very long time - perhaps the entire lifetime of the program. You can't really know without seeing all of the code that manipulates and manages Bar.



回答2:

I highly recommend reading the following article:

Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

It explains how the .NET runtime works at a low level, and explains internal nuances like Loader Heaps and how static classes/members work. Technically speaking, there IS an initial instantiation of the 'static instnace' of a classes static members. However, this initiation is handled by the runtime in a different way than it is handled for class instances. Static classes are stored on loader heaps, which are not GC managed. Loader heaps are allocated and grown in a static manner, and are not compacted. The article is a great read, and should give you a thourough understanding of how the CLR operates.

(NOTE: I am not certain of how valid this article is for .NET 4. I do know that there were GC changes in .NET 4, however I am not sure how many fundamental runtime changes there are. The introduction of the DLR and other features may deviate from the explanation in the above article to some degree.)



回答3:

Foo does not need to be instantiated, neither will it get instantied upon the SomeCheck static method call as per result, you would get the value returned by the method itself, and not an instance of the class.

Please have a look at these references for further details:

  1. Static vs Non-Static Methods;
  2. Static Classes and Static Class Members (C# Programming Guide).

I do hope this helps! =)



回答4:

It depends on the implementation of SomeMethod. The method will have to be invoked from somewhere, presumably a "driver" class which would instantiate Bar and call SomeMethod. For example:

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

Given your current implementation of SomeMethod, yes, you'd have to instantiate it.

However, as long as SomeMethod only makes a call to another static method, we could make make it static too. In which case you wouldn't have to create an instance of Bar to invoke the method. i.e.

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


回答5:

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");
            }
        }
    }

Yes you need to create an instance of Bar but not for Foo class since it is a static metod. Only difference is, the static methods are called at class level(compile time) rather than object level(run time), so you don't need to instantiate the Foo class.