It is only recently known that the trigger rules for static constructors of struct and class are different, unlike class, which triggers a static constructor the first time the class is used. A static constructor call is not triggered if a field that accesses only the struct instance. The test found that when accessing a static field, the function (static and instance) of the struct itself and the constructor with parameters can cause the execution of the static constructor. Calling both the default and the overridden base class virtual functions is not. Why, then?
Let's take a look at the difference between class and struct when calling a constructor. Class uses the newobj directive and struct uses the initobj directive to construct the object. Newobj requests a piece of memory on the heap and invokes the corresponding constructor to initialize it, and then returns the object address to the calculation stack. Initobj loads the struct instance that has already been allocated from the local variable table and initializes the struct fields. This initialization process is performed internally by the CLR, not as the class compiler adds a default constructor to class (which is why struct cannot add a default value to a field). However, if you add a default value compiler to a field in the class, the field assignment action is automatically added to the constructor. If a constructor with parameters is defined in the struct, the system does not use the initobj instruction, but instead calls the constructor with the parameter directly with the call instruction.
The most common instruction for calling functions is call and callvirt. For static functions, use the call instruction to use the callvirt instruction for class (regardless of whether the function in class is not virtual). The call instruction is used only when the subclass calls the function of the parent class (avoid recursive calls) and in the constructor (the compiler adds the Guaranteed parent class field to be initialized). And for struct we find that as long as the function being invoked is defined by the struct itself, the call instruction is used. The difference between call and callvirt instructions is that calling treats the called function as a static function without caring whether the instance pointer (this) is empty when the current function is invoked. This is what struct calls because the struct instance cannot be set to NULL. In fact, class is actually using call when calling a non-virtual function, just doing one more step to verify that--this is empty, let's verify that.
Class Class_test
{
public void Test1 () {}
public virtual void Test2 ()
{}
public static void Test3 () {}
public override string ToString ()
{
Return base. ToString ();
}
}
Class_test C = new class_test
();
C.test1 ();
C.test2 ();
Class_test.test3 ();
String str = c.tostring ();