Team LiB
Previous Section Next Section

Elements of C# Style

One of the trademarks of a good programmer is that they produce readable code. Your professional life will probably not involve generating code by yourself on a mountaintop, and so your colleagues will need to be able to work with and modify your programs. Here are some guidelines and conventions that will help you to produce clear, readable C# programs.

Proper Use of Indentation

One of the best ways to make C# programs readable is through proper use of indentation to clearly delineate statement hierarchies. Statements within a block of code should be indented relative to the starting/end line of the enclosing block (i.e., indented relative to the lines carrying the braces). The examples in the MSDN web pages use four spaces, but some programmers use two spaces and others prefer three. The examples in this book use a two-space indentation convention.

To see how indentation can make a program readable, consider the following two programs. In the first program, no indentation is used:

using System;

public class StyleDemo
{
static void Main() {
string name = "cheryl";
for (int i = 0; i < 4; i++) {
if (i != 2) {
Console.WriteLine(name + " " + i);
}
}
Console.WriteLine("what's next");
}
}

It's easy to see how someone would have to go through this program very carefully in order to figure out what it's trying to accomplish; it's not very readable code.

Now let's look at the same program when proper indentation is applied. Each statement within a block is indented two spaces relative to its enclosing block. It's much easier now to see what the code is doing. It's clear, for example, that the if statement is inside of the for statement's code block. If the if statement condition is true, the WriteLine method is called. It's also obvious that the last WriteLine method call is outside of the for loop. Both versions of this program produce the same result when executed, but the second version is much more readable.

using System;

public class StyleDemo
{
  static void Main() {
    string name = "Cheryl";
    for (int i = 0; i < 4; i++) {
      if (i != 2) {
        Console.WriteLine(name + " " + i);
      }
    }
    Console.WriteLine("What's next");
  }
}

This code's output is shown here:

Cheryl 0
Cheryl 1
Cheryl 2
What's next

Failure to properly indent makes programs unreadable and hence harder to debug—if a compilation error arises due to imbalanced braces, for example, the error message often occurs much later in the program than where the problem exists. For example, the following program is missing an opening brace on line 12, but the compiler doesn't report an error until line 26!

using System;
public class Indent2
{
  static void Main() {
    int x = 2;
    int y = 3;
    int z = 1;

    if (x >= 0) {
      if (y > x) {
        if (y > 2) // missing opening brace here on line 12, but ...
          Console.WriteLine("A");
          z = x + y;
        }
        else {
          Console.WriteLine("B");
          z = x - y;
        }
      }
      else {
        Console.WriteLine("C");
        z = y - x;
      }
    }
    else Console.WriteLine("D"); // compiler first complains here! (line 26)
  }
}

The error message that the compiler generates in such a situation is rather cryptic; it points to line 26 as the problem:

IndentDemo.cs (26,5) error CS1519: Invalid token.

and doesn't really help us much in locating the real problem on line 12. However, at least we've properly indented, so it will likely be easier to hunt down the missing brace than it would be if our indentation were sloppy.

Sometimes, we have so many levels of nested indentation, or individual statements are so long, that lines "wrap" when viewed in an editor or printed as hardcopy:

while (a < b) {
    while (c > d) {
    for (int j = 0; j < 29; j++) {
      x = y + z + a + b - 125
(c * (d / e) + f) - g + h + j - l - m - n + o +
p * q / r + s;
      }
    }
}

To avoid this, it is best to break the line in question along white space or punctuation boundaries:

while (a < b) {
  while (c > d) {
    for (int j = 0; j < 29; j++) {
      // This is cosmetically preferred.
      x = y + z + a + b - (c * (d / e) + f) - g +
          h + j - l - m - n + o + p * q / r + s;
    }
  }
}

Use Comments Wisely

Another important feature that makes code more readable is the liberal use of meaningful comments. Always keep in mind when writing code that you know what you're trying to do, but someone else trying to read your code may not. (We sometimes even need to remind ourselves of why we did what we did if we haven't looked at code that we've written in a while!)

If there can be any doubt as to what a section of code does, add a comment.

  • Include enough detail in the comment to clearly explain what you mean.

  • Make sure that the comment adds value; don't state the obvious. The following is a fairly useless comment because it states the obvious:

            // Declare x as an integer, and assign it an initial value of 3.
            int x = 3;
    
  • Indent each comment to the same level as the block of code or statement to which it applies.

For an example of how comments are important in making code readable, let's revisit an example from earlier in the chapter:

using System;

public class IfDemo
{
  static void Main() {
    double sales = 40000.0;
    int lengthOfService = 12;
    double bonus;

    if (sales > 30000.0 && lengthOfService >= 10) {
      bonus = 2000.0;
    }
    else {
      if (sales > 20000.0) {
        bonus = 1000.0;
      }
      else {
        bonus = 0.0;
      }
    }
    Console.WriteLine("Bonus = " + bonus);
  }
}

Because of the lack of comments, someone trying to read the code might have difficulty figuring out what business logic this program is trying to apply. Now let's look at the same program when clear, descriptive comments have been included in the code listing:

using System;

// This program computes the size of an employee's bonus.
//
// Written on January 5, 2004 by Jacquie Barker and Grant Palmer.

public class IfDemo
{
  static void Main() {
    // Quarterly sales in dollars.
    double sales = 40000.0;

    // Length of employment in months.
    int lengthOfService = 12;

    // Amount of bonus to be awarded in dollars.
    double bonus;

    // An employee gets a $2K bonus if (a) they have worked for the company
    // for 10 months or more and (b) they've sold more than $30K this quarter.
    if (sales > 30000.0 && lengthOfService >= 10) {
      bonus = 2000.0;
    }
    else {
      // Otherwise, ANY employee who has sold more than $20K this quarter earns a
      // bonus of $1K, regardless of how long they've worked for the company.
      if (sales > 20000.0) {
        bonus = 1000.0;
      }
      // Employees who have sold less than $20K earn no bonus.
      else {
        bonus = 0.0;
      }
    }

    Console.WriteLine("Bonus = " + bonus);
  }
}

The program is now much more understandable because the comments explain what each section of the code is intended to accomplish; i.e., the business logic of the application.

Placement of Braces

For block structured languages that use braces, { }, to delineate the start/end of blocks (e.g., C, C++, Java, C#), there are two general schools of thought as to where the left/opening brace of a code block should be placed.

The first style is to place the left brace at the end of the line of code that starts the block, and the matching right/closing brace on a line by itself.

Left brace is on the same line as the class declaration:

public class Test {

Ditto for method headers:

    static void Main() {

And ditto yet again for control flow statements:

        for (int i = 0; i < 3; i++) {
          Console.WriteLine(i);

Each closing brace goes on its own line:

        }
      }
    }

An alternative opening brace placement style is to place every opening brace on a line by itself:

  public class Test
  {
      static void Main()
      {
        for (int i = 0; i < 3; i++)
        {
          Console.WriteLine("i");
        }
      }
    }

The C# convention is a hybrid of these two approaches: in C#, we typically use the second style (brace on a separate line) for class declarations, and the first style (brace on the same line) for virtually everything else:

  public class Test
      {
       static void Main() {
          for (int i = 0; i < 3; i++) {
            Console.WriteLine(i);
          }
        }
      }

There is no absolute right or wrong style, in that the compiler doesn't care one way or the other. It is a good practice to maintain consistency in your code, however, so pick a brace placement style and stick with it.

Either way, it is important that the closing brace for a given block be indented the same number of spaces as the first line of code in the block so that they visually line up, as was discussed earlier.

Self-Documenting Variable Names

As with indentation and comments, the goal when choosing variable names is to make a program as readable, and hence self-documenting, as possible. Avoid using single letters as variable names, except for loop control variables. Abbreviations should be used sparingly, and only when the abbreviation is commonly used and widely understood by developers. Consider the following variable declaration:

  int grd;

It's not completely clear what the variable name "grd" is supposed to represent. Is the variable supposed to represent a grid, a grade, or a gourd? A better practice would be to spell the entire word out:

  int grade;

At the other end of the spectrum, names that are too long—such as perhaps

  double averageThirdQuarterReturnOnInvestment;

can make a code listing overwhelming to anyone trying to read it. It can sometimes be challenging to reduce the size of a variable name and still keep it descriptive, but do try to keep the length of your variable names within reason.

Note?/td>

We'll talk about naming conventions for other OO building blocks, such as methods and classes, as we introduce these topics later in the book.

The .NET Framework provides a series of naming guidelines to promote a uniform style across C# programs. If you'd like to read the complete details on the C# naming conventions, the guidelines can be found at the following URL: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconnamingguidelines.asp


Team LiB
Previous Section Next Section