27.2 Standard attributes


Most of the time you will be using a standard attribute provided by the .NET framework. Standard attributes are 'picked up' and interpreted by the C# compiler to have special meanings. Unlike custom attributes, you do not need to write a special attribute class to use them. They have either been coded “ and are part of the .NET BCLs “ or are implicitly understood by the C# compiler.

I will examine two of the three standard attributes reserved by C# first “ Obsolete and Conditional . The third reserved attribute, AttributeUsage , is a bit special and is discussed in Chapter 28.

27.2.1 The Obsolete attribute

This attribute is used to mark types and type members that should no longer be used. [7] You can use this attribute on classes, structures, and members such as delegates, methods , constructors, properties, fields, and events. Here is an example of how the Obsolete attribute can be used.

[7] Such members are described as 'deprecated' in Java terminology.

 1:  using System;  2:  3:  public class ClassB{  4:  5:  [Obsolete()]  6:    private int MyInteger;  7:  8:    public static void Main (){  9:      ClassA a = new ClassA(); 10:    } 11: 12:    public int PerformOp (int i){ 13:      MyInteger = i; 14:      return i*2; 15:    } 16:  } 17: 18:  [Obsolete("There are problems with this class")]  19:  public class ClassA{ 20:    // codes 21:  } 

Compiler warning:

 c:\expt>csc test.cs test.cs(9,5): warning CS0618: 'ClassA' is obsolete: 'There are problems with this class' test.cs(9,20): warning CS0618: 'ClassA' is obsolete: 'There are problems with this class' test.cs(13,5): warning CS0612: 'ClassB.MyInteger' is obsolete 

In the example above, I have tagged ClassA (on line 18) and field MyInteger (on line 5) as obsolete using the [Obsolete] attribute specification. During compilation, warning messages inform you about that. If you are using csc.exe , note that the compilation warning messages appear only when there are attempts to use the entities tagged as Obsolete . (If you comment out line 9, the obsolete warning for ClassA will not appear because ClassA is never used).

Another observation is that you can pass into the Obsolete attribute specification either nothing (line 5) or a string (line 18). If nothing is passed in, a default warning is shown. If a string is passed in, the string is shown as the warning message. In fact, the Obsolete attribute can take in an additional boolean parameter:

 [Obsolete ("My message", true)] 

The boolean parameter is the error parameter. If true is passed in, a compilation error is created instead of a warning.

Remember the attribute class needed to write our own custom attributes I mentioned briefly ? Just keep in mind that the possible parameters an attribute specification can take in is determined by the different overloaded constructors written in this attribute class. For Obsolete , you can imagine that the ObsoleteAttribute class has three overloaded constructors “ one which takes in nothing, one which takes in a string, and one which takes in a string and a boolean parameter. I will revisit this idea in writing our custom attribute classes.

27.2.2 The Conditional attribute

This section assumes that you understand preprocessor directives and conditional compilation (see Chapter 24) but skipping this section will not affect your understanding of the remaining material in this chapter.

The Conditional attribute can be used instead of the #if , #elif , and #else preprocessor directives for conditional compilation. By tagging a method as Conditional , that method may or may not be included in the resultant IL codes, depending on whether a particular symbol has been defined. Study the example below:

 1:  #define DEBUG   2:  using System;   3:  using System.Diagnostics;   4:   5:  public class TestClass{   6:   7:    public static void Main (){   8:    PerformOp();    9:      Console.WriteLine("Finishing Main");   10:    }  11: 12:  [Conditional("DEBUG")]   13:    public static void PerformOp (){   14:      Console.WriteLine("Running PerformOp");   15:    }   16:  }  

Output:

 c:\expt>test Running PerformOp Finishing Main 

Line 3 has to be included so that the Conditional attribute class can be found by the compiler.

Notice that the DEBUG symbol is #define d on line 1. The PerformOp method (lines 13 “ 15) has been tagged with the Conditional attribute specification, which takes in a string as parameter (line 12). In this case, the DEBUG symbol is passed into the Conditional attribute specification. What line 12 effectively says, is if the DEBUG symbol is defined, compile the PerformOp method normally. Otherwise, do not compile the PerformOp method “ or any other statements in the code that invoke the PerformOp method (such as line 8) “ into IL codes.

The output shows that PerformOp() has been invoked, as expected, in Main() .

Let's comment off line 1, so that the DEBUG symbol is not defined.

 1:  // #define DEBUG  2:  using System;   3:  using System.Diagnostics;   4:   5:  public class TestClass{   6:   7:    public static void Main (){  8:  PerformOp();   9:      Console.WriteLine("Finishing Main");   10:    }  11: 12:  [Conditional("DEBUG")]  13:    public static void PerformOp (){ 14:      Console.WriteLine("Running PerformOp"); 15:    }  16:  }  

Output:

 c:\expt>test Finishing Main 

In this case, the whole PerformOp method (lines 13 “ 15) is being ignored, together with any invocations of PerformOp (line 8) during compilation. The shaded lines are the lines which eventually make it into IL codes, and the new output reflects exactly that.

Conditional can only take in a single string, and can only be applied to methods. You cannot use it to tag classes, fields, and other class entities. There are some other special rules concerning its use:

  • Methods tagged as Conditional must return void . Otherwise it would be very difficult for the compiler to ignore all method invocations, especially if it is part of other C# expressions!

  • Methods tagged as Conditional must not be declared with the override modifier, [8] though it may be declared with the virtual modifier. This does not mean that overriding methods cannot be Conditional (see next rule).

    [8] In C# (unlike Java), all class members that are to be overridden in subclasses must be declared with the virtual modifier, and members in a subclass that are overriding a member of the same identifier in its superclass must be declared with the override modifier. See section 7.10.

  • When virtual methods, which are marked as Conditional , are overridden in subclasses, that overriding method will automatically become Conditional too. However, you cannot explicitly tag that overriding method with the Conditional attribute specification, since it is already implicitly so. [9]

    [9] In the next chapter, where I shall discuss more about the parameters of AttributeUsage , you will see that the Conditional attribute's behavior is what is called 'inherited'.

Not following these rules will simply result in a compilation error.

27.2.3 Other standard attributes

Table 27.1 gives a brief description of other standard attributes in the .NET framework. There are many others not listed.

Table 27.1. Standard attributes

Standard attribute

Description

Serializable

Used to tag components which are to be serialized

DllImport

Used to specify the DLL location that contains the definition for an extern method. [1]

StructLayout

Used to specify the layout (in memory) of the fields of a struct “ this attribute can only be applied to structs and classes

WebMethod

Used to tag methods which are to be exposed as XML web services

CLSCompliantAttribute

Used to tag assemblies, modules, types, and class members as compliant with the CLS, or not

[1] An extern method is one which is declared but not implemented locally. The implementation for an extern method is usually found in some legacy COM DLLs. The DllImport attribute tags a method as being defined in some external DLL.

In the code fragment below, the [Serializable] attribute is applied to the class MyClass . This tells the compiler to make the class serializable:

 [Serializable] public class MyClass {   // codes here } 

I shall discuss how to write custom attributes in the next chapter.



From Java to C#. A Developers Guide
From Java to C#: A Developers Guide
ISBN: 0321136225
EAN: 2147483647
Year: 2003
Pages: 221
Authors: Heng Ngee Mok

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net