Results 1 to 4 of 4

Thread: Optional and named parameters in an Attribute..?

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Optional and named parameters in an Attribute..?

    Hi,

    I have a custom Attribute class where the constructor takes one fixed parameter and two optional parameters. It is my understanding that one can supply one or more optional parameters by using 'named parameters' such as this:
    Code:
    Private Sub CallMethod()
       Me.OptionalMethod(-1, z:=1)
    End Sub
    
    Private Sub OptionalMethod(ByVal x As Integer, Optional ByVal y As Integer = 0, Optional ByVal z As Integer = 10)
       '...
    End Sub
    This way I skip the 'y' parameter and simply let it use the default value of 0. This works fine for any class, except apparently for attributes...

    This is my attribute class:
    vb.net Code:
    1. <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)> _
    2.     Public Class GridOptionsAttribute
    3.         Inherits System.Attribute
    4.  
    5.         Public Sub New(ByVal visible As Boolean, Optional ByVal text As String = Nothing, Optional ByVal index As Integer = -1)
    6.             _DisplayName = text
    7.             _Visible = visible
    8.             _DisplayIndex = index
    9.         End Sub
    10.  
    11.         Private _DisplayName As String
    12.         Public ReadOnly Property DisplayName() As String
    13.             Get
    14.                 Return _DisplayName
    15.             End Get
    16.         End Property
    17.  
    18.         Private _Visible As Boolean
    19.         Public ReadOnly Property Visible() As Boolean
    20.             Get
    21.                 Return _Visible
    22.             End Get
    23.         End Property
    24.  
    25.         Private _DisplayIndex As Integer
    26.         Public ReadOnly Property DisplayIndex() As Integer
    27.             Get
    28.                 Return _DisplayIndex
    29.             End Get
    30.         End Property
    31.  
    32.     End Class

    When I try to use it, I cannot seem to use named parameters:


    Huh?

    Well, I thought, perhaps Attributes don't support named parameters. I know they can behave a little weird (they don't support all types in their arguments for example I think), so I thought little of it.

    But then... I noticed something else. If you take a look at my code of the attribute class again. Notice that I am using an attribute on that class as well... And what do you know: named parameters. Working just fine... The AttributeUsage attribute has the exact same configuration: one fixed parameter and two optional parameters. I seem to be able to call them using named parameters just fine, where I cannot call my own attribute constructor with named parameters...

    What's going on... Am I losing my mind? Is VS bugged? Or is it infected with a demon?

  2. #2
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Optional and named parameters in an Attribute..?

    Attributes don't really work in a standard manner here. I want to say they actually predate Optional arguments in VB .NET, but I can't remember if that's right or not. At the very least, I know how it does work.

    Peek at AttributeUsage's constructor. See any optional arguments? Nope. So how does it get to use optional arguments?

    Attributes are treated specially, that's how. The .NET CLR doesn't actually require that a language support optional parameters, and for a long time C# didn't support them. But it was definitely a boon to have optional parameters for attribute declarations, so a weirdo compiler trick was used instead.

    For attribute classes (and only classes used as attributes), here is the convention. Positional "unnamed" parameters are specified as arguments to the constructor of the class. They are expected to have the same name as read-only properties of the class, but allowed to differ by case. Named parameters are not listed in the constructor, but instead listed as read/write properties of the class. When you specify a named parameter, the compiler uses reflection to verify that the parameter name corresponds to a read/write property and generates code to set the value of that property after constructing the attribute object. In this way, languages that don't support optional/named parameters (like C# up to 4.0 but technically no .NET language was *required* to implement them) can still use something like them for attributes.

    Thus, when you design an attribute, you have to follow these rules:
    • You should only have properties that you intend to correspond to parameters that are set when the attribute is applied.
    • Any properties you intend to be required should be read-only and have a corresponding constructor parameter that sets them.
    • Any properties you intend to be optional or named should be read/write and not be part of the constructor.

    It's a bit messed up, but it's the best they could do in .NET 1.0.

    *edit*
    Found an MSDN entry that explains it in a sort of roundabout way.

  3. #3
    PowerPoster JuggaloBrotha's Avatar
    Join Date
    Sep 2005
    Location
    Lansing, MI; USA
    Posts
    4,286

    Re: Optional and named parameters in an Attribute..?

    I thought named attributes were added to .Net 2.0 for better COM compatibility. Though I didn't see people using them until VS2008 and even then the only ones I'd ever seen used were one those 'Declare Function' calls to an external COM object or an API call to shell.dll

    Outside of that the only other time I've ever seen them used are in vb6/vba apps, which is basically COM based anyways.

    I guess I've just never really seen a practical use for them in .Net yet.
    Currently using VS 2015 Enterprise on Win10 Enterprise x64.

    CodeBank: All ThreadsColors ComboBoxFading & Gradient FormMoveItemListBox/MoveItemListViewMultilineListBoxMenuButtonToolStripCheckBoxStart with Windows

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Optional and named parameters in an Attribute..?

    Quote Originally Posted by Sitten Spynne View Post
    Attributes don't really work in a standard manner here. I want to say they actually predate Optional arguments in VB .NET, but I can't remember if that's right or not. At the very least, I know how it does work.

    Peek at AttributeUsage's constructor. See any optional arguments? Nope. So how does it get to use optional arguments?

    Attributes are treated specially, that's how. The .NET CLR doesn't actually require that a language support optional parameters, and for a long time C# didn't support them. But it was definitely a boon to have optional parameters for attribute declarations, so a weirdo compiler trick was used instead.

    For attribute classes (and only classes used as attributes), here is the convention. Positional "unnamed" parameters are specified as arguments to the constructor of the class. They are expected to have the same name as read-only properties of the class, but allowed to differ by case. Named parameters are not listed in the constructor, but instead listed as read/write properties of the class. When you specify a named parameter, the compiler uses reflection to verify that the parameter name corresponds to a read/write property and generates code to set the value of that property after constructing the attribute object. In this way, languages that don't support optional/named parameters (like C# up to 4.0 but technically no .NET language was *required* to implement them) can still use something like them for attributes.

    Thus, when you design an attribute, you have to follow these rules:
    • You should only have properties that you intend to correspond to parameters that are set when the attribute is applied.
    • Any properties you intend to be required should be read-only and have a corresponding constructor parameter that sets them.
    • Any properties you intend to be optional or named should be read/write and not be part of the constructor.

    It's a bit messed up, but it's the best they could do in .NET 1.0.

    *edit*
    Found an MSDN entry that explains it in a sort of roundabout way.
    Thanks. I knew C# didn't support named or optional parameters before .NET 4.0, but I've always thought they were part of VB.NET and hence could be used in Attributes (as long as you were working in VB) as usual. Apparently not. It's getting late so I haven't read all of it yet, I'll do that tomorrow.

    Quote Originally Posted by JuggaloBrotha View Post
    I thought named attributes were added to .Net 2.0 for better COM compatibility. Though I didn't see people using them until VS2008 and even then the only ones I'd ever seen used were one those 'Declare Function' calls to an external COM object or an API call to shell.dll

    Outside of that the only other time I've ever seen them used are in vb6/vba apps, which is basically COM based anyways.

    I guess I've just never really seen a practical use for them in .Net yet.
    Do you mean named parameters? Or specifically named parameters in attributes? Named parameters are quite common aren't they? I can see great practical use for them, as long as you have a method with a lot of optional parameters. If you have a method with, say, 10 optional parameters and you only want to specify the last one, then without named parameters you could either:
    1. Supply the default value for each parameter (so you have to look them up), or
    2. Leave it empty, resulting in a method call like
    Code:
    Me.SomeMethod(,,,,,,,,,"Finally..")
    Yeah... not really the syntactic sugar VB promised to have

    With named parameters you just do
    Code:
    Me.SomeMethod(lastValue:="Finally..")
    Much easier to read.


    And even with normal methods I can see some use for them. If you are calling some method that you don't really know, I find it useful to supply the parameter names just so I can see what the various values do. For example, this:
    Code:
    Me.CountElements(CountStrings:=True, CountIntegers:=True, CountDates:=False, CountDoubles:=False)
    is much easier to read at a glance then
    Code:
    Me.CountElements(True, True, False, False)
    unless you know exactly in which order the parameters are declared.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width