Core8: Attribute Targets
[This post is part of a series, "wish-list for future versions of VB"]
IDEA: Attribute Targets. We should allow some more attribute targets of the form <Target:SomeAttribute()>. Currently the only permitted targets are Assembly: and Module: , so we should add Field: and Property:.
Note that VB has traditionally used "positional attribute placement" where possible, rather than C#'s attribute targets...
Function f() As <CLSCompliant(True)> Integer
[return:CLSCompliant(true)] int f()
We would keep with position attribute placement where possible, and use attribute targets only when positional placement would be ambiguous.
Here is a complete list of all possible attribute targets in C#, and the ones highlighted in yellow are simply inexpressible in VB at the moment. VB should be able to express all of these (apart from the [return:] target on void-returning functions!)
[assembly:Fred]
[module:Fred]
[type:Fred] public struct S { }
[type:Fred] public interface I { }
[type:Fred] enum E { }
[type:Fred] [return:Fred] delegate int D();
[type:Fred] class C { }
public class Program
{
[method:Fred] [return:Fred] void m([param:Fred] int x) { }
[method:Fred] [return:Fred] static public Program operator +(Program p) { return null; }
[field:Fred] static int f;
[property:Fred] public int p { [method:Fred] [return:Fred] get {return f;} [method:Fred] [param:Fred] [return:Fred] set {} }
[property:Fred] public int this[[param:Fred] int i] {[method:Fred] [return:Fred] get{return i;} [method:Fred] [param:Fred] [return:Fred] set{}}
[event:Fred] [field:Fred] [method:Fred] static event System.Action e;
[event:Fred] static event System.Action c {[method:Fred] [param:Fred] add { } [method:Fred] [param:Fred] remove { } }
static void Main() { f = 0; System.Console.WriteLine(f); e += () => { }; }
}
class FredAttribute : System.Attribute { }
In addition to these, there are some attribute targets that we should add which C# currently can't express.
SCENARIO: "I’m having an issue with the way the VB compiler interprets WithEvents fields and the resulting code that is placed in the compiled assembly. Specifically, when you add custom attributes on WithEvents fields, the attributes remain on the underlying field but do not get propagated to the generated property that contains the logic for adding or removing event handlers. The scenario we’re trying to enable involves placing the DebuggerBrowsable attribute on the WithEvents fields so that it does not show up as a member when looking at an instance of the declaring type in the debugger watch window. Since the attribute does not propagate, we’ve been unable to remove WithEvents fields from the list. Do you know if there was an explicit decision to not propagate these events, or it’s just something that was overlooked?"
Actually, this scenario makes the ideal design unclear. It seems to be asking for a <Property:> target. But do we want propagation for all attributes, no questions asked, based on the applicability of the attribute? i.e. whether it applies to fields or properties or whatever else?
Incidentally, VB10 introduced one special case of attribute propagation. It allows the <NonSerialized> attribute to be declared on an event; however, the attribute is placed on the event's backing field rather than the event itself. This was to support the following scenario:
<NonSerialized()>
Event PropertyChanged As PropertyChangedEventHandler
We should also consider introducing a target <Field:> for auto-properties.
Incidentally, VB should really let you provide attributes on any parameters, but it currently only allows attributes on plain old method declarations -- not on property setters, not on default property indexes, not on inline event declarations, not on accessors in custom event declarations. This just seems inconsistent.
Provisional evaluation from VB team: This is a decent idea, one that we should consider against the other decent ideas. We seem to have covered the common needs already, but we're worried that there are other scenarios we're not spotting. If you've encountered scenarios where you were stymied by the lack of targeted attributes, please let us know!