Constructor call is valid only as the first statement in an instance constructor.

rbulph

Junior Contributor
Joined
Feb 17, 2003
Messages
397
The IDE tells me that, in the constructor of an inheriting class, calls to MyBase.New must be the first line. This leads to me writing code like:

Code:
Inherits System.ComponentModel.CategoryAttribute

Public Sub New(ByVal x as long)

        MyBase.New(IIf(x=1, "One", "Two"))
    
End Sub

With more complicated conditions you can imagine that the IIfs are going to get ridiculous. Why will it not just let me write:


Code:
Inherits System.ComponentModel.CategoryAttribute

Public Sub New(ByVal x as long)

        Dim s as string
        If x= 1 then
            s="One"
        Else
            s="Two"
        End If
        MyBase.New(s)

End Sub
And is there a solution to the problem?

Edit: OK, I see that I can call a function in the parameter of MyBase.New, and as long as this function isn't in the inheriting class, it will work OK. So I can manage. Still, any comments welcome.
 
Last edited:
In the constructor of the derived class you could be calling functionality or accessing members declared in the base class(es), the base constructors need to be run before any code in the derived class' constructor to ensure that this underlying code is in a consistent and initalised state.

If you are doing lots of complex work then perhaps a constructor isn't the best choice and you might need to consider an alternative method.
 
The next question, I would imagine, would be "What alternatives are there to a constructor?" so I'll offer a couple.

Both alternatives are seen from time in the .Net framework, though the first is encountered more often. Neither example does something you can't do with a normal constructor, but they demonstrate alternatives that don't have the same restrictions and can be more straightforward in certain cases.

One option is to have no public constructors and instead provide a static method that can be used to obtain instances. This allows you to apply logic before you call a constructor.
Visual Basic:
Class ExampleClass
    ' Private constructor, only methods defined in this class can instantiate this class.
    Private Sub New (int v)
        Base.New(v)
    End Sub
  
    ' This is the function that must be called to get an instance of this class
    Public Sub GetInstance(numericValue As Integer)
        ' You can place logic here before creating the object, for example
        ' confirm that a value is positive before passing it on to the base
        ' constructor
        If numericValue < 0 Throw New ArgumentException("The value must be positive.")
        Return New ExampleClass(numericValue)
    End Sub
End Class
The other option is to use a creation-parameters class, where instead of passing a number of parameters to a constructor which needs to process the parameters before calling the base constructor, you create a creation-parameter object, assign values to it, process logic internally in the creation-parameter object, and then finally pass that object as the sole parameter to the constructor of the object you want to instantiate.
Visual Basic:
'We want to create an ExampleClass object. To do so, we must create a CreateParams
'object, assign data to it, and pass it to an ExampleClass constructor.
 
Class CreateParams
    'We can use properties now, instead of constructor parameters
 
    Dim _examplePropertyBackingField As Integer
    Public Property ExampleProperty As Integer
        Get
            Return _examplePropertyBackingField
        End Get
        Set
            ' Pre-process you creation parameters here, before we even invoke the
            ' ExampleClass constructor.
            If value < 0 Throw New ArgumentException ("Value must be positive.")
            _examplePropertyBackingField = value
        End Set
    End Property
End Class
 
Class ExampleClass {
    Public Sub New(cp As CreationParams) 
    ' Now we don't need to do any processing here because it was already done in 
    ' the CreationParams object.
        Base.New(cp.ExampleProperty)
    End Sub
End Class

Hope that helps.
 
Thanks. What I'm trying to achieve is a CategoryAttribute that can only have certain string values for the category. Doing that allows me to select from a choice of categories (through the Intellisense) when I create a new property, rather than having to type in the text of the category each time (and risk getting it slightly different, and so inadvertently creating a new category). The difficulty is that there isn't anywhere to set properties of the CategoryAttribute other than through the constructor since you have to create it as part of the declaration of the property. There is no "room" to follow either of your suggestions, marble-eater. As I say, I have managed to do this to my satisfaction, and I've used code as follows:

Code:
<CustomCategory(CatTypes.WeatherDetails)> Public Property Get Rainfall as decimal
'Get, Set etc.
End Property

<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)> Public Class CustomCategory
    Inherits CategoryAttribute

    Public Sub New(ByVal c As CatType)

        MyBase.New(CatDesc(c))

    End Sub

End Class


Public Module Module1

    Public Enum CatTypes
        WeatherDetails
        TaxDetails
        CityDetails
    End Enum

    Public Function CatDesc(ByVal ct As CatTypes) As String

        Select Case ct
            Case CatTypes.WeatherDetails
                Return "Weather Info"
            Case CatTypes.TaxDetails
                Return "Tax"
            Case CatTypes.CityDetails
                Return "Cities"
        End Select

    End Function

End Module

P.S. how do you get code to come out in colours as in marble-eater's post? I'm using the code tags, and you can see the result isn't as good.
 
You get the syntax highlighting by using the vb tags instead of code tags. The code tags are a generic way of wrapping code regardless of the language. Using the vb tags or cs tags will highlight a specific language.

What I generally do in the situation you described is have a protected method that contains the code I would normal put in the constructor. Then have the child class call this at whatever point it needs to. Heres a little example.
Visual Basic:
 Public Class Parent
    '
    Protected Sub Init()
        ' have constuctor stuff here
    End Sub
    '
End Class
'
Public Class Child
    Inherits Parent
    '
    Public Sub New()
        ' set some properties as required here....
        ' then call init method
        Init()
    End Sub
    '
End Class
 
Cags said:
You get the syntax highlighting by using the vb tags instead of code tags. The code tags are a generic way of wrapping code regardless of the language. Using the vb tags or cs tags will highlight a specific language.

What I generally do in the situation you described is have a protected method that contains the code I would normal put in the constructor. Then have the child class call this at whatever point it needs to. Heres a little example.
Visual Basic:
 Public Class Parent
    '
    Protected Sub Init()
        ' have constuctor stuff here
    End Sub
    '
End Class
'
Public Class Child
    Inherits Parent
    '
    Public Sub New()
        ' set some properties as required here....
        ' then call init method
        Init()
    End Sub
    '
End Class
Yes, except I can't do that here because the CategoryAttribute class is part of System.ComponentModel and is not something that I created.
 
Back
Top