How come you can pass an array into a C# attribute class but not a VB.NET attribute class?

Q: In C# you can pass an array into an attribute class using the code below but when you try to do this from VB.NET you get an error. Why can’t you do this in VB.NET?

public sealed class FooAttribute : Attribute

{

       private int[] intarr;

       public int[] IntArray

       {

              set

              {

                     intarr = value;

              }

              get

              {

                     return intarr;

              }

       }

}

[Foo(IntArray=new int[]{1,2,3})]

class Class1

{

              }

<Foo(New Integer() {1, 2, 3} )> _

Public Class test

    Public x As Integer() = {1, 2, 3}

End Class

Public NotInheritable Class FooAttribute

    Inherits Attribute

    Private intarr() As Integer

    Public Sub New()

    End Sub

    Public Property IntArray() As Integer()

        Get

            Return intarr

        End Get

        Set(ByVal Value As Integer())

            intarr = Value

        End Set

    End Property

End Class 'FooAttribute

Error: Constant expression is required.

A: The language specification for Visual Basic .NET does not allow for expressions to be passed in as arguments within Attribute Blocks. Attribute block arguments must be constant expressions. You can call methods with the expression “New Integer() {}” . There is a tiny blurb in the docs that mentions this: Note that in Visual Basic, constructors for an attribute class should not use a ParamArray argument.

 

While the above VB.NET code does not work, the following does work.

    test(New Integer() {1, 2, 3})

where test is defined as:

    Public Sub test(ByVal x As Integer())

    End Sub

Here’s the language definition for both Application Block Arguments and Method Call Arguments

Attribute Arguments

AttributeArguments ::=
AttributePositionalArgumentList |
AttributePositionalArgumentList , VariablePropertyInitializerList |
VariablePropertyInitializerList

AttributePositionalArgumentList ::=
ConstantExpression |
AttributePositionalArgumentList , ConstantExpression

VariablePropertyInitializerList ::=
VariablePropertyInitializer
VariablePropertyInitializerList , VariablePropertyInitializer

VariablePropertyInitializer ::= Identifier : = ConstantExpression

Argument Lists

ArgumentList ::=
PositionalArgumentList , NamedArgumentList |
PositionalArgumentList |
NamedArgumentList

PositionalArgumentList ::=
ArgumentExpression |
PositionalArgumentList , [ ArgumentExpression ]

NamedArgumentList ::=
Identifier : = ArgumentExpression |
NamedArgumentList , Identifier : = ArgumentExpression

ArgumentExpression ::= Expression| DelegateArgumentExpression

For a similar issue regarding Attributes and why you can do somethings in VB.NET but not C# see Eric Gunnerson’s post: https://blogs.msdn.com/csharpfaq/archive/2004/05/11/130236.aspx