Public Shared Readonly Member optimized out in VB.

2019-07-18 15:50发布

I have this weird behavior in VB.Net I am stuck with. At the moment I am not able to determine whether I am missing some concept or it is a bug.

I have a base class:

Public MustInherit Class BaseType(Of T As BaseType(Of T)) :
    Implements IEquatable(Of BaseType(Of T))
    Protected Sub New(key As Integer, value As List(Of String))
        LogManager.GetLogger("INFO").Info("Strings: " & vbTab & value.Count())
        If key <> -1 Then
            enumValues.Add(CType(Me, T))
        End If
    End Sub

    Protected Shared Function TypeFromStringBase(name As String) As T
        For Each b As T In enumValues
            LogManager.GetLogger("DEBUG").Info(b.Names(0))
            If b.Names.Contains(name) Then
                Return b
            End If
        Next

        Return TypeFromStringBase("Keine")
    End Function
End Class

And a Class that inherits it:

Public Class AnschlussType : Inherits BaseType(Of AnschlussType) :
    Implements IEquatable(Of AnschlussType)
    Public Shared ReadOnly Rund As New AnschlussType(1, {"Rund", "1"})
    Public Shared ReadOnly Flach As New AnschlussType(2, {"Flach", "2"})
    Public Shared ReadOnly Gewinde As New AnschlussType(3, {"Gewinde", "3"})
    Public Shared ReadOnly Kein As New AnschlussType(4, {"Kein", "None", "4"})

    Private Sub New(key As Integer, names As String())
        MyBase.New(key, names.ToList())
    End Sub

    Public Shared Function TypeFromString(name As String) As AnschlussType
        Return TypeFromStringBase(name)
    End Function
End Class

Here is the weird part I don't get. The first time you call AnschlussType.TypeFromString("Some String"), VB should create all the Public Shared ReadOnly members. This results in four calls to BaseType.New. Each of those calls then adds it's own type to the enumValues List.

After all those initializations, finally, the AnschlussType.TypeFromString call will be executed. There it calls TypeFromStringBase which iterates over the enumValues List we filled right before.

This all works fine in the DEBUG mode.

Here is the weird part I don't get. Now I tried RELEASE mode. The enumValues.Count would always stay 0. I assumed this because the logger does not print anything, which means it doesn't iterate, which means it is zero. So I investigated a little more and put a logging statement into BaseType.New. And this does NOT log at all. This leads me to the conclusion that New is not executed at all.

Let me emphasize that this all works great in DEBUG mode and with other subtypes that have Public Shared ReadOnly members in the same matter. But this does not work in RELEASE mode.

Does anyone have a hint for me what I could be missing?

1条回答
Anthone
2楼-- · 2019-07-18 16:50

If a static constructor (Section 10.11) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

Assuming VB works like C#, your shared (i.e. static) fields aren't being initialized because you haven't used them.

Try creating a shared constructor.

查看更多
登录 后发表回答