CSharp/C# Tutorial - C# Attributes






Attributes can add custom information to code elements.

For example, we can use attribute to mark a class is deprecated.

We can also mark an interface is a web interface for web service.

Attribute Classes

An attribute is defined by a class that inherits from the abstract class System.Attribute.

To attach an attribute to a code element, specify the attribute's type name in square brackets, before the code element.

For example, the following code attaches the ObsoleteAttribute to the Main class:


[ObsoleteAttribute]
public class Main {
   ...
}

This attribute is recognized by the compiler and will cause compiler warnings if a type or member marked obsolete is referenced.

By convention, all attribute types end in the word Attribute.

C# allows you to omit the suffix when attaching an attribute:


[Obsolete]
public class Main {
   ...
}

ObsoleteAttribute is a type declared in the System namespace as follows:


public sealed class ObsoleteAttribute : Attribute {...}

The C# language and the .NET Framework include a number of predefined attributes.





Named and Positional Attribute Parameters

Attributes may have parameters.

In the following example, we apply XmlElementAttribute to a class.

This attribute tells XML serializer how an object is represented in XML and accepts several attribute parameters.

The following attribute maps the CustomerEntity class to an XML element named Customer, belonging to the http://java2s.com namespace:


[XmlElement ("Customer", Namespace="http://java2s.com")]
public class Customer { 
   ... 
}

Attribute parameters fall into one of two categories: positional or named.

In the preceding example, the first argument is a positional parameter; the second is a named parameter.

Positional parameters correspond to parameters of the attribute type's public constructors.

Named parameters correspond to public fields or public properties on the attribute type.

When specifying an attribute, we must include positional parameters that correspond to one of the attribute's constructors.

Named parameters are optional.





Attribute Targets

Here is an example of using the CLSCompliant attribute to specify CLS compliance for an entire assembly:


[assembly:CLSCompliant(true)]

Specifying Multiple Attributes

Multiple attributes can be specified for a single code element.

Each attribute can be listed either within the same pair of square brackets separated by a comma or in separate pairs of square brackets.

The following three examples are semantically identical:


[Serializable, Obsolete, CLSCompliant(false)]
public class Main {...}

[Serializable] [Obsolete] [CLSCompliant(false)]
public class Main {...}

[Serializable, Obsolete]
[CLSCompliant(false)]
public class Main {...}

Caller Info Attributes

We can tag optional parameters with one of three caller info attributes. They tell the compiler to feed information obtained from the caller's source code into the parameter's default value:

  • [CallerMemberName] applies the caller's member name
  • [CallerFilePath] applies the path to caller's source code file
  • [CallerLineNumber] applies the line number in caller's source code file

The OneMethod method in the following program demonstrates all three:


using System;/*from  w ww  .  j a  va 2s  .c  om*/
using System.Runtime.CompilerServices;

class Main {
    static void Main(){
        OneMethod();
    }
    static void OneMethod (
        [CallerMemberName] string memberName = null,
        [CallerFilePath] string filePath = null,
        [CallerLineNumber] int lineNumber = 0){
        
            Console.WriteLine (memberName);
            Console.WriteLine (filePath);
            Console.WriteLine (lineNumber);
    }
}

Assuming our program resides in c:\source\test\Program.cs, the output would be:


Main
c:\source\test\Program.cs
11