Previous Section  < Day Day Up >  Next Section

15.1. Following .NET Code Design Guidelines

The developers of .NET included a set of rules [1] that are intended to serve as a guide for writing code that runs on the .NET platform. Although the rules are written with component developers in mind (Microsoft uses them for its managed code libraries), any application can benefit from them.

[1] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconnetframeworkdesignguidelines.asp

To help a developer incorporate these rules and best practices in their code, .NET includes the FxCop tool that analyzes code against these rules. Some of the rules may be stricter than your development environment requires; or they may simply conflict with your own standards梱ou may prefer non-Microsoft naming conventions, for instance. To accommodate your own coding standards, the tool permits you to disable rules and add custom ones. Figure 15-2 shows how rules are displayed with check boxes that make it easy to enable or disable them.

Figure 15-2. FxCop allows rules to be enabled or disabled by clicking a check box


FxCop is available as both a GUI (fxcop.exe) and command line (fxcopcmd.exe) application. Downloads of the latest version and documentation are free and available at several Web locations. The download also includes an SDK that can be used to create custom rules梐 topic beyond the scope of this section.

Using FxCop

The purpose of FxCop is to analyze an assembly and produce output that pinpoints code features that violate the set of recommended best practices. To illustrate how it works, let's create an assembly from the code in Listing 15-1 and run it through FxCop. The program is a simple console application that accepts an input string, reverses it, and prints it. A simple menu permits the user to specify whether she wants to reverse a string or quit.

To test with FxCop, compile the program and pass the assembly to FxCop:


C:/> csc fxtest.cs

C:/> fxcopcmd  /file:fxtest.exe  /out:fxoutput.txt


Due to the length of the output, it's better to direct it to a file rather than display it.

Listing 15-1. Code to Be Analyzed by FxCop

//fxtest.cs

using System;

using System.Text;

namespace FxTesting

{

   public class TestApp 

   {

      static void Main()

      {

         string msg;

         string oper="";

         while(oper !="Q")

         {

            Console.WriteLine("(R)everse, (Q)uit");

            oper= Console.ReadLine();

            oper = oper.ToUpper();

            if(oper=="R"){

               Console.WriteLine("Enter phrase to reverse:");

               msg= Console.ReadLine();

               if(msg.Length>1) msg= Reverse(msg);

               Console.WriteLine(msg);

         }

      }

   }

   // Function to reverse a string

   public static String Reverse(String stringParameter)

   {

      if(stringParameter.Length==1)

      {

         return stringParameter;

      }

         else

         {

            return Reverse(stringParameter.Substring(1)) + 

                           stringParameter.Substring(0,1);

         }

      }

   }

}


The output is serialized as XML that contains Message tags, describing each occurrence where the code does not conform to the recommended practices. Here is an example of the raw code comprising one message:


<Message TypeName="AssembliesShouldHaveValidStrongNames" 

   Category="Microsoft.Design" Check Status="Active" 

   Created="2005-01-12 02:41:07Z" FixCategory="NonBreaking"> 

   <Issue Name="NoStrongName" Certainty="95"  

      Level="CriticalError">Sign 'fxtest' with a strong name key.

   </Issue>

</Message>


Let's look at the analysis FxCop produces for the fxtest assembly. For brevity, only the TypeName values from the XML are listed. Beneath each is a description of the code changes that will eliminate the message:

(1)

"AssembliesShouldDeclareMinimumSecurity"

Requires adding a permission attribute that specifies the permissions required by this assembly. This is explained in Section 15.3 of this chapter.

(2)

"AssembliesShouldHaveValidStrongNames"

Assembly should be assigned a strong name, which is a key that identifies the assembly. Assigning strong names is described in Section 15.2 of this chapter.

(3)

"MarkAssembliesWithAssemblyVersion"

Add version attribute: [assembly: AssemblyVersion("1.0.0.0")].

(4)

"MarkAssembliesWithClsCompliant"

Add compliant attribute: [System.CLSCompliant(true)]

(5)

"MarkAssembliesWithComVisible"

Add ComVisible attribute: [ComVisible(true)].

This exposes public managed assemblies and types to COM. By default, they are not visible to COM.

(6)

"StaticHolderTypesShouldNotHaveConstructors"

Because the class TestApp has only static members, it should not have a public constructor. In this case, the public constructor is the default parameterless constructor. To override this, add: private TestApp() {}.

(7)

"AvoidUnnecessaryStringCreation"

To avoid allocating memory for strings, string operations should be avoided. The solution is to eliminate oper = oper.ToUpper(); and to use case- insensitive comparisons in the code, such as if(string.Compare(oper, "R", true)==0).

(8)

"AvoidTypeNamesInParameters"

Naming rules recommend that type names not be included as part of a parameter name. In this case, it objects to the parameter name stringParameter.


A review of the output shows that the assembly recommendations (1 through 5) are oriented toward components that will be stored in libraries and used by other code. As one would expect, the emphasis is on how component code interacts with other code. In general, security and type visibility is of more importance here than in general application development. Recommendations 6 and 7 promote more efficient code, whereas rule 8 is a subjective naming convention.

Many of the rules are overly restrictive for most programming environments, and you'll want to disable them. However, it is beneficial to be aware of them. They represent a set of best practices that have evolved with .NET. Even if you do not incorporate them in your code, understanding the reasoning behind them will deepen your knowledge of .NET.

    Previous Section  < Day Day Up >  Next Section