Search code examples
c#.netvb.netclassloaderstatic-constructor

Is there a standard way for .NET class loaders to work?


Is there a standard way for .NET class loaders to work?

Say I compile this code:

Option Strict On : Option Explicit On

Module Module1
    Sub Main()
        System.Diagnostics.Debug.WriteLine("Main")
        Dim g = C.A
    End Sub
End Module

Public Class C
    Shared Sub New()
        System.Diagnostics.Debug.WriteLine("Init C")
    End Sub
    Shared Property A As New A
End Class

Public Class A
    Shared Sub New()
        System.Diagnostics.Debug.WriteLine("Init A")
    End Sub
    Public Sub New()
        System.Diagnostics.Debug.WriteLine("A Constructor")
    End Sub
End Class

Can I guarantee the compiled code will (in all implemented platforms) have the following output?

Main
Init A
A Constructor
Init C

Solution

  • Because you are using constructors and not inline initialization, the VB compiler does not mark the types with beforefieldinit, and the order is exactly controlled.

    If, however, you wrote the following (using inline initialization):

    Option Strict On : Option Explicit On
    
    Module Module1
        Sub Main()
            System.Console.WriteLine("Main")
            Dim g = C.A
        End Sub
    End Module
    Public Class C
        Shared Function Narg() As A
            Dim alpha As New A
            System.Console.WriteLine("Init C")
            Return alpha
        End Function
        Shared Property A As A = Narg()
    End Class
    Public Class A
        Shared Sub New()
            System.Console.WriteLine("Init A")
        End Sub
        Public Sub New()
            System.Console.WriteLine("A Constructor")
        End Sub
    End Class
    

    the order would be unspecified. The same order as your original code would be allowed, but C can be initialized earlier. In fact, on my system the output is:

    Init A
    A Constructor
    Init C
    Main
    

    The reason is that C now is marked beforefieldinit.


    Gratuitous nit-picking: No, your original code is not guaranteed to have that output. On a release build it will have no output, because System.Diagnostics.Debug is conditionally called.