Predefined .NET Attributes
Many attributes are provided with the .NET implementation; however, not all of them are included in the CLI Standard. They are all derived directly from System::Attribute, which, in turn, is derived directly from System::Object. Some examples are:
System::CLSCompliantAttribute System::Diagnostics::ConditionalAttribute System::FlagsAttribute System::NonSerializedAttribute System::ObsoleteAttribute System::ParamArrayAttribute System::Runtime::InteropServices::DllImportAttribute System::Runtime::InteropServices::FieldOffsetAttribute System::Runtime::InteropServices::InAttribute System::Runtime::InteropServices::OutAttribute System::SerializableAttribute System::ThreadStaticAttribute
Enum Value Formatting
In a previous installment, the following reader exercise was proposed: "Many enum types are defined simply to have a set of named constants with distinct values. Others are defined with enumerators whose initial values are explicitly initialized with distinct values that are a power of two (as in 1, 2, 4, 8, etc.). Define a CLI enum type having the latter and create an instance whose value is the bitwise-or of multiple enumerators. Display the value of that instance. Then apply the attribute [Flags] to that CLI enum type and run the program again. What is the difference? Read the documentation on the type System::FlagsAttribute." The following example is a solution to a slight variation of that problem:
using namespace System; public enum class Color {Red = 1, Blue = 2, Yellow = 4}; [Flags] public enum class Position {Left = 1, Right = 2, Top = 4, Bottom = 8}; int main() { /*1*/ Console::WriteLine(Color::Red); /*2*/ Console::WriteLine(Color::Red | Color::Blue); /*3*/ Console::WriteLine(Color::Red | Color::Blue | Color::Yellow); /*4*/ Console::WriteLine(Position::Left); /*5*/ Console::WriteLine(Position::Left | Position::Right); /*6*/ Console::WriteLine(Position::Left | Position::Right | Position::Top); }
The output produced, is as follows:
Red 3 7 Left Left, Right Left, Right, Top
The CLI classifies enum constants into two categories: enumeration constants and bit-fields (which are not to be confused with C++'s own bit-fields). Quoting the CLI: "Bit-fields are generally used for lists of elements that might occur in combination; whereas enumeration constants are generally used for lists of mutually exclusive elements. Therefore, bit-fields are designed to be combined with the bitwise OR operator to generate unnamed values, whereas enumerated constants are not." Using that classification, Position's members are bit-fields while Color's are not, and the presence of the [Flags] attribute on Position's definition indicates that for certain operations, such as formatted output, combinations of enum values should be handled differently.