Free mag vol1 | Page 639

CHAPTER 15  TYPE REFLECTION, LATE BINDING, AND ATTRIBUTE-BASED PROGRAMMING { // ... } As an alternative, you can also apply multiple attributes on a single item by stacking each attribute as follows (the end result is identical): [Serializable] [Obsolete("Use another vehicle!")] public class HorseAndBuggy { // ... } C# Attribute Shorthand Notation If you were consulting the .NET Framework 4.5 SDK documentation, you might have noticed that the actual class name of the [Obsolete] attribute is ObsoleteAttribute, not Obsolete. As a naming convention, all .NET attributes (including custom attributes you may create yourself) are suffixed with the Attribute token. However, to simplify the process of applying attributes, the C# language does not require you to type in the Attribute suffix. Given this, the following iteration of the HorseAndBuggy type is identical to the previous (it just involves a few more keystrokes): [SerializableAttribute] [ObsoleteAttribute("Use another vehicle!")] public class HorseAndBuggy { // ... } Be aware that this is a courtesy provided by C#. Not all .NET-enabled languages support this shorthand attribute syntax. Specifying Constructor Parameters for Attributes Notice that the [Obsolete] attribute is able to accept what appears to be a constructor parameter. If you view the formal definition of the [Obsolete] attribute using the Code Definition window (which can be opened using the View menu of Visual Studio), you will find that this class indeed provides a constructor receiving a System.String. public sealed class ObsoleteAttribute : Attribute { public ObsoleteAttribute(string message, bool error); public ObsoleteAttribute(string message); public ObsoleteAttribute(); public bool IsError { get; } public string Message { get; } } Understand that when you supply constructor parameters to an attribute, the attribute is not allocated into memory until the parameters are reflected upon by another type or an external tool. The string data defined at the attribute level is simply stored within the assembly as a blurb of metadata. 581