C# 程式碼風格指南

原文:C# Coding Conventions (C# Programming Guide)

Naming Conventions

Qualified names can be broken after a dot . if they are too long for a single line, as shown in the following example.

1
2
var currentPerformanceCounterCategory = new System.Diagnostics.
PerformanceCounterCategory();

Layout Conventions

  • four-character indents, tabs saved as spaces
  • Write only one statement per line.
  • Write only one declaration per line.
  • If continuation lines are not indented automatically, indent them one tab stop (four spaces).
  • Add at least one blank line between method definitions and property definitions.
  • Use parentheses to make clauses in an expression apparent, as shown in the following code.
    • if ((val1 > val2) && (val1 > val3))

Commenting Conventions

  • Place the comment on a separate line, not at the end of a line of code.
  • Begin comment text with an uppercase letter.
  • End comment text with a period.
  • Insert one space between the comment delimiter // and the comment text
    1
    2
    // The following declaration creates a query. It does not run
    // the query.
  • Do not create formatted blocks of asterisks around comments.

Language Guidelines

  • Use string interpolation to concatenate short strings, as shown in the following code.
    • string displayName = $"{nameList[n].LastName}, {nameList[n].FirstName}";
  • To append strings in loops, especially when you are working with large amounts of text, use a StringBuilder object.
    1
    2
    3
    4
    5
    6
    7
    var phrase = "la";
    var manyPhrases = new StringBuilder();
    for (var i = 0; i < 10000; i++)
    {
    manyPhrases.Append(phrase);
    }
    //Console.WriteLine("tra" + manyPhrases);

Implicitly Typed Local Variables

  • Use implicit typing for local variables when the type of the variable is obvious from the right side of the assignment, or when the precise type is not important.
    1
    2
    var var1 = "This is clearly a string.";
    var var2 = 27;
  • Do not use var when the type is not apparent from the right side of the assignment.
    • A variable type is considered clear if it’s a new operator or an explicit cast.
      1
      2
      int var3 = Convert.ToInt32(Console.ReadLine());
      int var4 = ExampleClass.ResultSoFar();
  • Use implicit typing to determine the type of the loop variable in for loops.
  • Do not use implicit typing to determine the type of the loop variable in foreach loops.

Arrays

Use the concise syntax when you initialize arrays on the declaration line.

1
2
3
4
5
6
7
8
// Preferred syntax. Note that you cannot use var here instead of string[].
string[] vowels1 = { "a", "e", "i", "o", "u" };
// If you use explicit instantiation, you can use var.
var vowels2 = new string[] { "a", "e", "i", "o", "u" };
// If you specify an array size, you must initialize the elements one at a time.
var vowels3 = new string[5];
vowels3[0] = "a";
vowels3[1] = "e";

Delegates

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Define the type.
public delegate void Del(string message);

// Define a method that has a matching signature.
public static void DelMethod(string str)
{
Console.WriteLine("DelMethod argument: {0}", str);
}

// In the Main method, create an instance of Del.
// Preferred: Create an instance of Del by using condensed syntax.
Del exampleDel2 = DelMethod;
// The following declaration uses the full syntax.
Del exampleDel1 = new Del(DelMethod);

Simplify your code by using the C# using statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Method1: try-finally statement with Dispose
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
{
((IDisposable)font1).Dispose();
}
}

// Method2: Using statement.
using (Font font2 = new Font("Arial", 10.0f))
{
byte charset = font2.GdiCharSet;
}

&& and || Operators

  • To avoid exceptions and increase performance by skipping unnecessary comparisons, use && instead of & and || instead of | when you perform comparisons
    • The && operator short circuits when the first expression is false
    • The & operator evaluates both, and causes a run-time error when divisor is 0.
      1
      2
      3
      4
      5
      6
      7
      8
      if ((divisor != 0) && (dividend / divisor > 0))
      {
      Console.WriteLine("Quotient: {0}", dividend / divisor);
      }
      else
      {
      Console.WriteLine("Attempted division by 0 ends up here.");
      }

New Operator

  • Use var in when using new: var instance1 = new ExampleClass();
  • Use object initializers to simplify object creation.
    • var instance3 = new ExampleClass { Name = "Desktop", ID = 37414, Location = "Redmond", Age = 2.3 };

Event Handling

  • If you are defining an event handler that you do not need to remove later, use a lambda expression.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public Form2()
    {
    // You can use a lambda expression to define an event handler.
    this.Click += (s, e) =>
    {
    MessageBox.Show(
    ((MouseEventArgs)e).Location.ToString());
    };
    }

    // Using a lambda expression shortens the following traditional definition.
    public Form1()
    {
    this.Click += new EventHandler(Form1_Click);
    }

    void Form1_Click(object sender, EventArgs e)
    {
    MessageBox.Show(((MouseEventArgs)e).Location.ToString());
    }

Static Members

  • Call static members by using the class name: ClassName.StaticMember
    • This practice makes code more readable by making static access clear.
    • Do not qualify a static member defined in a base class with the name of a derived class.

LINQ Queries

  • Use meaningful names for query variables.
    1
    2
    3
    var seattleCustomers = from customer in customers
    where customer.City == "Seattle"
    select customer.Name;
  • Use aliases to make sure that property names of anonymous types using Pascal casing.
    1
    2
    3
    4
    var localDistributors =
    from customer in customers
    join distributor in distributors on customer.City equals distributor.City
    select new { Customer = customer, Distributor = distributor };
  • Use implicit typing in the declaration of query variables and range variables.
  • Align query clauses under the from clause, as shown in the previous examples.
  • Use multiple from clauses instead of a join clause to access inner collections.
    1
    2
    3
    4
    5
    // Use a compound from to access the inner sequence within each element.
    var scoreQuery = from student in students
    from score in student.Scores
    where score > 90
    select new { Last = student.LastName, score };