Question <Attribute>: ParamArray in Constructor

VentureFree

Well-known member
Joined
Jan 9, 2008
Messages
54
Programming Experience
5-10
A former co-worker wrote a class in C# that was to be used as an attribute. I'm having to convert his work to VB (yeah, it's pointless and way more work than necessary, but management thinks it's a good idea). Unfortunately I'm having an issue because one of the main properties of the class is an ArrayList which is set with a ParamArray in the constructor. The class looks like this (note I've tried to abstract out the problem, so this is a simplified version of the class only)
VB.NET:
<AttributeUsage(AttributeTargets.Field Or AttributeTargets.[Property])> _
Public Class LabelAttribute
    Inherits Attribute
    Public Sub New()
        m_Labels = New ArrayList()
    End Sub 'New

    Public Sub New(ByVal ParamArray NewLabels As [String]())
        m_Labels = New ArrayList(NewLabels)
    End Sub 'New
	
    Private m_Labels As ArrayList = Nothing
    Private m_Description As [String] = Nothing
	
    Public ReadOnly Property Labels() As ArrayList
        Get
            Return m_Labels
        End Get
    End Property 'Labels

    Public Property Description() As [String]
        Get
            Return m_Description
        End Get
        Set(ByVal value As [String])
            m_Description = value
        End Set
    End Property 'Description
End Class 'LabelsAttribute
To use this, I would be adding the attribute to shared variables as follows:
VB.NET:
<Label("Label1")> _
Private Shared s_MyFirstVariable As [String]

<Label("Label1", "Label2")> _
Private Shared s_MySecondVariable As [String]

' Broken! "Description" should be the description, not another label
<Label("Label1", "Label2", "Description")> _
Private Shared s_MyThirdVariable As [String]
In the first one, there is just the single label being added. No Problem. In the second one there are 2 different labels being added. Again, no problem. The third one, however, is a problem because it's assuming that the "Description", which is supposed to be the description is instead being interpreted as another label.

This wasn't a problem in C# because it could be set as follows:
VB.NET:
[Label("Label1", "Label2", Description="Description")]
private static string s_MyThirdVariable;
Of course this doesn't work in VB because optional parameters aren't referred to by name as they are in C#. As a stopgap I've changed the constructor to allow only a single label like this
VB.NET:
Public Sub New(ByVal NewLabel As [String])
    m_Labels = New ArrayList()
    m_Labels.Add(NewLabel)
End Sub 'New
but that undermines some of what this class is meant to do. Does anyone know how, or even if I can get the same basic functionality to work in VB?

I can't help but think there must be a way to make the existing design work. Imagine this class was built into a library that I could not modify. Would I be forever forbidden from setting Description because of this design? One would hope not. But maybe I'm wrong and it's just bad design to begin with.

Anyway, thanks for any help that you might be able to offer.
 
You can in VB refer to any parameter by name:
VB.NET:
Description:="Description"
 
Hmm...every time I tried it gave me an error. Looking online it seemed that you could essentially skip optional parameters by using blank arguments, but that you couldn't actually refer to them by name in VB. For example, a sub with the definition Public Sub MySub(ByVal Param1 As Integer, Optional ByVal Param2 As Integer = 0, Optional ByVal Param3 As Integer = 0) could be called like MySub(1, , 1) to set Param3 without setting Param2, but that was all.

It's definitely possible that I am simply wrong on this. I'm not at work at the moment, and I don't have my dev environment set up at home, so I'll give it another try tomorrow and see if I just missed something. Thanks.
 
You probably didn't type it correctly. Naming parameters when passing arguments is a old VB feature, Optional is irrelevant. Here's the help article about it: Passing Arguments by Position and by Name (Visual Basic)
Note that the ParamArray NewLabels is not a property when applying the attribute metadata, so this can't be referred to by name, and has to come first.
 
Thank you very much. I wasn't typing the colon. I fell victim to the old "If the answer is not on the first page of a Google search, then it doesn't exist" syndrome which I've chided my friends on. The link that you provided was actually halfway down page 2. A little persistence (and I mean even a minuscule amount) would have done me good.

For any lurkers, here's the answer:

VB.NET:
Public Sub MySub(ByVal Param1 As Integer, Optional ByVal Param2 As Integer = 0, Optional ByVal Param3 As Integer = 0)
    ' Code here
End Sub

' You can either use the method I outlined above to set Param3 without setting Param2
MySub(1, , 1)
' Or you can use the following to set Param3 directly
' Note the colon, which is what I was missing
MySub(1, Param3:=1)
 
Back
Top