What are attributes in .NET?
Asked Answered
C

11

211

What are attributes in .NET, what are they good for, and how do I create my own attributes?

Corroboree answered 21/8, 2008 at 15:59 Comment(0)
W
150

Metadata. Data about your objects/methods/properties.

For example I might declare an Attribute called: DisplayOrder so I can easily control in what order properties should appear in the UI. I could then append it to a class and write some GUI components that extract the attributes and order the UI elements appropriately.

public class DisplayWrapper
{
    private UnderlyingClass underlyingObject;

    public DisplayWrapper(UnderlyingClass u)
    {
        underlyingObject = u;
    }

    [DisplayOrder(1)]
    public int SomeInt
    {
        get
        {
            return underlyingObject .SomeInt;
        }
    }

    [DisplayOrder(2)]
    public DateTime SomeDate
    {
        get
        {
            return underlyingObject .SomeDate;
        }
    }
}

Thereby ensuring that SomeInt is always displayed before SomeDate when working with my custom GUI components.

However, you'll see them most commonly used outside of the direct coding environment. For example the Windows Designer uses them extensively so it knows how to deal with custom made objects. Using the BrowsableAttribute like so:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
    get{/*do something*/}
}

Tells the designer not to list this in the available properties in the Properties window at design time for example.

You could also use them for code-generation, pre-compile operations (such as Post-Sharp) or run-time operations such as Reflection.Emit. For example, you could write a bit of code for profiling that transparently wrapped every single call your code makes and times it. You could "opt-out" of the timing via an attribute that you place on particular methods.

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
    bool time = true;
    foreach (Attribute a in target.GetCustomAttributes())
    {
        if (a.GetType() is NoTimingAttribute)
        {
            time = false;
            break;
        }
    }
    if (time)
    {
        StopWatch stopWatch = new StopWatch();
        stopWatch.Start();
        targetMethod.Invoke(target, args);
        stopWatch.Stop();
        HandleTimingOutput(targetMethod, stopWatch.Duration);
    }
    else
    {
        targetMethod.Invoke(target, args);
    }
}

Declaring them is easy, just make a class that inherits from Attribute.

public class DisplayOrderAttribute : Attribute
{
    private int order;

    public DisplayOrderAttribute(int order)
    {
        this.order = order;
    }

    public int Order
    {
        get { return order; }
    }
}

And remember that when you use the attribute you can omit the suffix "attribute" the compiler will add that for you.

NOTE: Attributes don't do anything by themselves - there needs to be some other code that uses them. Sometimes that code has been written for you but sometimes you have to write it yourself. For example, the C# compiler cares about some and certain frameworks frameworks use some (e.g. NUnit looks for [TestFixture] on a class and [Test] on a test method when loading an assembly).
So when creating your own custom attribute be aware that it will not impact the behaviour of your code at all. You'll need to write the other part that checks attributes (via reflection) and act on them.

Winny answered 21/8, 2008 at 16:18 Comment(6)
For what it's worth, this is a list of all (built in) .NET attributes: msdn.microsoft.com/en-us/library/aa311259(VS.71).aspxSturm
How would you use your "SomeProfilingMethod" as an attribute?Cooperstein
@Cooperstein its not an attribute, SomeProfilingMethod is the instrumentation code that is looking for profiling attributes. Specifically in the example I gave its looking for an "opt-out" attribute (NoTimingAttribute) as opposed to an "opt-in" one. The idea is that it times everything.Winny
@Winny could you add something like "Attributes don't do anything by themselves - there needs to be some other code to use them (compiler cares about couple, different frameworks use some). Just creating attribute will not impact behavior of the code - you need to write the other part that checks attributes (via reflection) and act on them". (or I can do that if you are ok). Many people expect attributes to magically work and none of the answers here clarify that. (or just link to #4880021 which covers it)Conductor
only if you stop using Bing. Nah. j/k I use DuckDuckGo as my primary which mainly uses Bing iirc. :)Winny
btw you got any links to the sort of unfortunate expectations that devs have about features? Its a very interesting subject particularly considering how well the base framework was written to promote self-discovery.Winny
M
35

Many people have answered but no one has mentioned this so far...

Attributes are used heavily with reflection. Reflection is already pretty slow.

It is very worthwhile marking your custom attributes as being sealed classes to improve their runtime performance.

It is also a good idea to consider where it would be appropriate to use place such an attribute, and to attribute your attribute (!) to indicate this via AttributeUsage. The list of available attribute usages might surprise you:

  • Assembly
  • Module
  • Class
  • Struct
  • Enum
  • Constructor
  • Method
  • Property
  • Field
  • Event
  • Interface
  • Parameter
  • Delegate
  • ReturnValue
  • GenericParameter
  • All

It's also cool that the AttributeUsage attribute is part of the AttributeUsage attribute's signature. Whoa for circular dependencies!

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
Mablemabry answered 16/2, 2009 at 18:2 Comment(0)
D
14

Attributes are a kind of meta data for tagging classes. This is often used in WinForms for example to hide controls from the toolbar, but can be implemented in your own application to enable instances of different classes to behave in specific ways.

Start by creating an attribute:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

All attribute classes must have the suffix "Attribute" to be valid.
After this is done, create a class that uses the attribute.

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

Now you can check a specific class' SortOrderAttribute (if it has one) by doing the following:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

If you want to read more about this you can always check out MSDN which has a pretty good description.
I hope this helped you out!

Dibb answered 21/8, 2008 at 16:33 Comment(0)
I
5

An attribute is a class that contains some bit of functionality that you can apply to objects in your code. To create one, create a class that inherits from System.Attribute.

As for what they're good for... there are almost limitless uses for them.

http://www.codeproject.com/KB/cs/dotnetattributes.aspx

Inflation answered 21/8, 2008 at 16:0 Comment(1)
"functionality" is the wrong word here; they are metadata, not functionalityEncore
U
5

Attributes are like metadata applied to classes, methods or assemblies.

They are good for any number of things (debugger visualization, marking things as obsolete, marking things as serializable, the list is endless).

Creating your own custom ones is easy as pie. Start here:

http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx

Upswell answered 21/8, 2008 at 16:2 Comment(0)
R
5

In the project I'm currently working on, there is a set of UI objects of various flavours and an editor to assembly these objects to create pages for use in the main application, a bit like the form designer in DevStudio. These objects exist in their own assembly and each object is a class derived from UserControl and has a custom attribute. This attribute is defined like this:

[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
  ControlDescriptionAttribute (String ^name, String ^description) :
    _name (name),
    _description (description)
  {
  }

  property String ^Name
  {
    String ^get () { return _name; }
  }

  property String ^Description
  {
    String ^get () { return _description; }
  }

private:
  String
    ^ _name,
    ^ _description;
};

and I apply it to a class like this:

[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
  // stuff
};

which is what the previous posters have said.

To use the attribute, the editor has a Generic::List <Type> containing the control types. There is a list box which the user can drag from and drop onto the page to create an instance of the control. To populate the list box, I get the ControlDescriptionAttribute for the control and fill out an entry in the list:

// done for each control type
array <Object ^>
  // get all the custom attributes
  ^attributes = controltype->GetCustomAttributes (true);

Type
  // this is the one we're interested in
  ^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;

// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
  if (attributetype->IsInstanceOfType (attribute))
  {
    ECMMainPageDisplay::ControlDescriptionAttribute
      ^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);

    // get the name and description and create an entry in the list
    ListViewItem
      ^item = gcnew ListViewItem (description->Name);

    item->Tag = controltype->Name;
    item->SubItems->Add (description->Description);

    mcontrols->Items->Add (item);
    break;
  }
}

Note: the above is C++/CLI but it's not difficult to convert to C# (yeah, I know, C++/CLI is an abomination but it's what I have to work with :-( )

You can put attributes on most things and there are whole range of predefined attributes. The editor mentioned above also looks for custom attributes on properties that describe the property and how to edit it.

Once you get the whole idea, you'll wonder how you ever lived without them.

Roturier answered 21/8, 2008 at 16:54 Comment(0)
F
4

As said, Attributes are relatively easy to create. The other part of the work is creating code that uses it. In most cases you will use reflection at runtime to alter behavior based on the presence of an attribute or its properties. There are also scenarios where you will inspect attributes on compiled code to do some sort of static analysis. For example, parameters might be marked as non-null and the analysis tool can use this as a hint.

Using the attributes and knowing the appropriate scenarios for their use is the bulk of the work.

Forgat answered 21/8, 2008 at 16:43 Comment(0)
P
3

Attributes are, essentially, bits of data you want to attach to your types (classes, methods, events, enums, etc.)

The idea is that at run time some other type/framework/tool will query your type for the information in the attribute and act upon it.

So, for example, Visual Studio can query the attributes on a 3rd party control to figure out which properties of the control should appear in the Properties pane at design time.

Attributes can also be used in Aspect Oriented Programming to inject/manipulate objects at run time based on the attributes that decorate them and add validation, logging, etc. to the objects without affecting the business logic of the object.

Pragmatism answered 21/8, 2008 at 17:57 Comment(0)
E
2

You can use custom attributes as a simple way to define tag values in sub classes without having to write the same code over and over again for each subclass. I came across a nice concise example by John Waters of how to define and use custom attributes in your own code.

There is a tutorial at http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

Etruscan answered 21/8, 2008 at 16:2 Comment(0)
K
2

To get started creating an attribute, open a C# source file, type attribute and hit [TAB]. It will expand to a template for a new attribute.

Katrinakatrine answered 27/12, 2008 at 1:55 Comment(1)
How does it answer the question? it should be a comment, not an answer.Ultramicroscope
F
1

Attributes are also commonly used for Aspect Oriented Programming. For an example of this check out the PostSharp project.

Farther answered 21/10, 2009 at 20:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.