Warning due to conflict between Form's Shared Function and its Default Instance

VBobCat

Well-known member
Joined
Sep 6, 2011
Messages
137
Location
S?o Paulo, Brazil
Programming Experience
3-5
My project has a "Dialog" Form.
Its purpose is to allow user to select none, some or all itens among the content of a default array.
This default array with all possible choices must be dynamically generated on runtime.
This gets done by function defined into the class of that class.
Whenever needed, a new instance of this form is explicitly instanced (i.e. "Dim MyDialogX as New DialogX : Dim DialogXresponse= DialogX.ShowDialog()"), and user's selection is stored in a new array, of same type of that default one, which contains as many items as user has selected.
All this goes ok.
Sometimes, however, I need to get that default array directly, and I would like to do this without instancing a new form, to avoid overhead froim its layout and field instancing.
To accomplish that, I made that function - which dynamically generates this array - a shared one, and refer it via its base class whenever it is needed (i.e. "Dim DefaultArray = DialogX.GetDefaultArray()")
Albeit it works, I've got since then an everlasting annoying warning, "Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated"
Well, DialogX is not an instance, it is Class's Type itself. I understand that Forms have default instances in VB.NET and this is the cause of this confusion. I've read about it and learned that this is an issue of compatibility with VB6. However, I find disturbing that Type itself and one of its instances are ambiguously referred by the same statement.
My question is, can I disable a Form's self-generating default instance in order to get rid of this warning?
Thank you very much.
 
About your problem, I can't reproduce that in VB 2010 SP1. Would think the compiler handled it.

Beside the issue, but can you spot the error here:
"Dim MyDialogX as New DialogX : Dim DialogXresponse= DialogX.ShowDialog()"
 
About your problem, I can't reproduce that in VB 2010 SP1. Would think the compiler

Beside the issue, but can you spot the error here:

Yes, thanks, I typed that sample in a hurry. Of course, it should be "Dim MyDialogX as New DialogX : Dim DialogXresponse= MyDialogX.ShowDialog()"
 
About the issue itself, I was taught about two workarounds, and both work, so far as I tested them.
1. Move out the problematic method, so that it be no longer a shared function in form class, but an independent function in a module.
2. Have only parametrized constructors in the form class, so default instance can't be created.
I've chosen the latter, because I had alreay a parametrized constructor, and it was easy to get rid of the other one. Besides, it made sense to me keeping my function along the form class as a shared member, because its response relates to the settings which the form helps to perform, and nothing else. I didn't like it as a loose function in a module.
So, workarounds do exist. But... the possibility of ambiguous derivations from classes that implement unsolicited default instances remain as a source of awkwardness, from my point of view.
Anyway, thanks a lot!
 
The issue itself is precisely because of what John pointed out to you... but on a different line.

Dim MyDialogX as New DialogX
Dim DefaultArray = DialogX.GetDefaultArray()


Assuming GetDefaultArray is declared Shared, this should work. MyDialogX.GetDefaultArray() would not, because as the error message indicated, you cannot access a shared member, constant member, enum member or nested type through an instance.

Post some real code and we can probably easily spot the error for you.
 
Last edited:
I'm not aware of any issue when accessing a Shared member of a form class. I just did this:
Public Class Form1

    Public Shared Sub DoSomething()
        '...
    End Sub

End Class
Public Class Form2

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Form1.DoSomething()
    End Sub

End Class
in both VS 2010 and VS 2012 and it worked perfectly; no errors, no nothin'. If it's not working for you then I think that it's safe to say that you've done something wrong.
 
I should have specified you get this warning specifically when the shared member returns a value (and you get this value from an instance).

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim thisForm As New Form2

        Dim a = thisForm.SomethingElse
        Dim b = thisForm.GetSomething()

        Dim c = Form2.GetSomething()
        Dim d = Form2.SomethingElse

    End Sub
End Class

Public Class Form2
    Public Shared Function GetSomething() As Integer
        Return 10
    End Function

    Public Shared ReadOnly Property SomethingElse As Integer
        Get
            Return 20
        End Get
    End Property
End Class


A and B both give the warning, C and D do not. Note that it will compile, it's just VS telling you "Hey you declared those members Shared for a reason, you sure you want that value from an instance?". It has a point. lol...

From MSDN:

Accessing a Shared member through an instance variable can make your code more difficult to understand by obscuring the fact that the member is Shared. Furthermore, if such access is part of an expression that performs other actions, such as a Function procedure that returns an instance of the shared member, Visual Basic bypasses the expression and any other actions it would otherwise perform.

The highlighted part is important, because this "warning" (really should be an error) has a direct effect on your code flow.
 
Last edited:
I should have specified you get this warning specifically when the shared member returns a value (and you get this value from an instance).

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim thisForm As New Form2

        Dim a = thisForm.SomethingElse
        Dim b = thisForm.GetSomething()

        Dim c = Form2.GetSomething()
        Dim d = Form2.SomethingElse

    End Sub
End Class

Public Class Form2
    Public Shared Function GetSomething() As Integer
        Return 10
    End Function

    Public Shared ReadOnly Property SomethingElse As Integer
        Get
            Return 20
        End Get
    End Property
End Class


A and B both give the warning, C and D do not. Note that it will compile, it's just VS telling you "Hey you declared those members Shared for a reason, you sure you want that value from an instance?". It has a point. lol...

From MSDN:



The highlighted part is important, because this "warning" (really should be an error) has a direct effect on your code flow.
Whether or not you get the warning has nothing to do with whether or not the Shared member returns a value. You get the warning if you access a Shared member via an instance, plain and simple.
Public Class Form1

    Public Shared Sub DoSomething()
        '...
    End Sub

    Public Shared Function GetSomething() As Object
        '...
    End Function

    Public Shared Property Something As Object
    
End Class
Public Class Form2

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Form1.DoSomething()
        Dim x = Form1.GetSomething()
        Dim y = Form1.Something

        Dim f1 As New Form1

        f1.DoSomething()
        Dim a = f1.GetSomething()
        Dim b = f1.Something
    End Sub

End Class
In that case, the last three lines all produce the warning and the first three don't. Basically, the OP seems to think that the warning is occurring because the compiler is somehow confusing the class with its default instance but this example shows that that is not the case. If the OP is getting that warning then, assuming there's no corruption anywhere, they are accessing the member on an explicit reference. That's it, that's all.
 
Dear folks, I'm all the more thankful for your explanations, but, as I said from beginning, my code compiles and works. I get no errors. However, I was receiving this specific warning: "Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated" and my class' name taked a curly green underline, at the point I use its shared function to return the full array of options available, which I do when user doesn't open the dialog box to make a choice.

That seemed awkward because I called the shared member as a member of class type itself, not as a member from an instanced object of that class. I never created an instance of the class with the same name of the class type, nor knew that such a thing was possible.

It took me actually some time to grasp the concept of default instance in form-derived classes, and then I wanted to avoid that behavior.

I learned that I can do so by having only parametrized constructors. My dialog class had two, "Sub New()" and "Sub New(presets() as Object)". When I suppressed the first one, the warning was gone. Frow now on, when there are no presets, I pass Nothing as parameter, which the remaining constructor is prepared to test.

Anyway, I thank you all very much.
 
Back
Top