Anda di halaman 1dari 32

C# 3.

0 Coding Guidelines
Guidelines for .NET development

March 2009 Dennis Doomen

C# 3.0 Coding Guidelines Guidelines for .NET Development

1 General ........................................................................................................................................... 1
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 Introduction ............................................................................................................................................. 1 Goals ...................................................................................................................................................... 1 Visual Studio Code Analysis and Source Analysis ................................................................................. 1 Guidelines, not a standard ...................................................................................................................... 1 What about design patterns? .................................................................................................................. 2 Feedback and disclaimer ........................................................................................................................ 2 Contributions .......................................................................................................................................... 2 History .................................................................................................................................................... 2

2 3 4 5 6 7 8 9

Design Guidelines ......................................................................................................................... 3 Maintainability Guidelines ........................................................................................................... 8 Naming Guidelines ..................................................................................................................... 15 Performance Guidelines ............................................................................................................ 19 Usage Guidelines ........................................................................................................................ 20 Documentation Guidelines ........................................................................................................ 22 Layout Guidelines ....................................................................................................................... 24 Resources .................................................................................................................................... 26

10 List of Code Analysis Rules ...................................................................................................... 27

March 2009 Dennis Doomen

[ II ]

C# 3.0 Coding Guidelines Guidelines for .NET Development


This document attempts to provide useful and pragmatic guidelines for programming in C# 3.0 which we at Aviva Solutions already use in our day-to-day work. This idea started in 2002 when Vic Hartog (Philips Medical Systems) and I were assigned the task of writing up a coding standard for C# 1.0. Since then, I've tried to publish a similar document for C# 2.0, but because of a change of employer, I never officially published it other than through blog posts. In the last couple of months Ive received several requests from the community for an updated version of this document, preferably covering C# 3.0 as well. Moreover, I have become particularly fond of the power that Visual Studio's Code Analysis (FxCop) provides.


The coding guidelines have been written up for several reasons that should help writing high quality code that is easy to understand code and easy to maintain by (future) team members. Aviva Solutions applies code reviews to validate code quality, so it is important that all members of a project use the same style of coding. Style in this sense means using common constructs, writing proper documentation and code comments, and organizing code using a common layout.

Although complying with coding guidelines may seem to appear as undesired overhead or may limit creativity, this approach has already proven its value for many years. Moreover, not all coding guidelines have a clear rationale. Many of them are simply choices we made at Aviva Solutions. Additional goals include:


Preventing common mistakes and pitfalls. Preventing language constructs that are less comprehensive. Promoting object-oriented development.

Visual Studio Code Analysis and Source Analysis

Since the introduction of the first version of this document, Microsoft has spent a considerable amount of effort in helping us automating the review process. Static Code Analysis (FxCop) supports a wide range of rules covering both aspects such as this document covers and design guidelines on the usage of the .NET Framework. In this edition of the coding guidelines, we've removed all overlap with Code Analysis and added a list of recommended rules.

Another more recent effort is Source Analysis, a.k.a. StyleCop. But even though we really like it, its current ruleset does not allow sufficient flexibility to be pragmatic. For instance, we do want all public members to have proper documentation, but for many private members we don't need one. The current version of StyleCop does not allow you to choose this as an option yet.


Guidelines, not a standard

The document does not state that projects must comply with these guidelines, neither does it say which guidelines are more important than others. However, we encourage projects to decide themselves what guidelines are important, what deviations a project will use, who is the consultant in case doubts arise, and what kind of layout must be used for source code. Obvious, you should make these decisions before starting the real coding work. In general, generated code should not need to comply with coding guidelines. However, if it is possible to modify the templates used for generation, try to make them generate code that complies as much as possible.

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

1.5 What about design patterns?
We've received a few suggestions that were great on itself, but unfortunately where too much related to design principles and patterns. Even though I would love to to add these as well, it would have increased the size of the document significantly. Instead, I'd like to refer you to notable people like Martin Fowler, Jimmy Nilsson and Jeremy D. Miller.


Feedback and disclaimer

This document has been compiled using many contributions from both (ex) colleagues, sources from the Internet, and many years of developing in C#. If you have questions, comments or suggestions, please let us know by sending me an email at We will try to revise and republish this document with new insights, experiences and remarks on a regular basis. Notice though that it merely reflects our view on proper C# code so Aviva Solutions will not be liable for any direct or indirect damages caused by applying the guidelines of this document.

It is allowed to copy, adapt, and redistribute this document and its companion quick reference guide for noncommercial purposes or internal usage. However, you may not republish this document, or publish or distribute any adaptation of this document for commercial use without first obtaining express written approval from Aviva Solutions.


The following (prior) colleagues and members from the .NET community have contributed to this document both directly and indirectly (through web sites, articles and on-line discussions): Erwin Derksen (Ordina), Leendert Versluijs (Ordina), Matthijs den Haan (Ordina), John Dekkers (Ordina), Juwal Lovy (IDesign), Peter Ritchie (Independent MVP), Vic Hartog (Philips Medical Systems), William van Strien (Ordina), Martin Opdam (Aviva Solutions), Stephan Bookholt (Aviva Solutions), Jo-Wen Mei (Oosterkamp Training)


Jan 2006 Jan 2009 Initial version based on the Philips C# 1.0 Standard Major overhaul. Introduced recommended use of Code Analysis / FxCop and removed overlapping guidelines. Added C# 3.0 / LINQ coding guidelines. Mar 2009 First publication on the internet Dennis Doomen Dennis Doomen Dennis Doomen

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development


Design Guidelines
Do use a public static readonly field to define predefined object instances For example, consider a Color struct that stores a color internally as red, green, and blue components and this class has a constructor taking a numeric representation, then this class may expose several predefined colors like this. public struct Color { public static readonly Color Red = new Color(0xFF0000); public static readonly Color Black = new Color(0x000000); public static readonly Color White = new Color(0xFFFFFF); public Color(int redGreenBlue) { // implementation } }


Do mark classes that only contain static members as static The advantage of using a static class is that the compiler can make sure that no instance members are accidentally defined. The compiler will guarantee that instances of this class cannot be created and hence, relieves you of creating a private constructor such as was required in C# 1.0. Use a static class to contain methods that are not associated with a particular instance. For example: public static class EuroConversion { public static Decimal FromUSD(Decimal inUsd) { ... } public static Decimal ToUSD(Decimal inEuro) { ... } }


Do seal a class unless it has been designed for inheritance Defining a class sealed ensures that other classes cannot derive from it. Unless you have thought through the consequences of deriving from your class and have provided appropriate measurements (e.g. defined protected default constructors, defined virtual methods and properties, etc), define the class sealed. For example: public sealed class Book { public Book() { } }


Dont hide inherited members with the new keyword Not only does the new keyword break Polymorphism, one of the most essential object-orientation principles, it also makes subclasses more difficult to understand. Consider the following two classes: public class Book { public virtual void Print() { Console.WriteLine("Printing Book"); } } public class PocketBook : Book {

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

public new void Print() { Console.WriteLine("Printing PocketBook"); } } This will cause the following behavior which is not something you normally expect from class hierarchies. Book pocketBook = new PocketBook(); pocketBook.Print(); ((Book)pocketBook).Print(); // Will output "Printing PocketBook " // Will output "Printing Book"

It should not make a difference whether you call Print through the base class or the derived class. AV1011 It should be possible to treat a derived object as if it were a base class object In other words, it shall be possible to use a reference to an object of a derived class wherever a reference to its base class object is used without knowing the specific derived class. This rule is also known as the Liskov Substitution Principle (LSP). Please note that an interface is also regarded as a base class in this context. AV1015 Do allow properties to be set in any order Properties should be stateless with respect to other properties, i.e. there should not be a difference between first setting property DataSource and then DataMember, and vice versa. AV1016 Do use a method, rather than a property, in the following situations

The operation is orders of magnitude slower than a field set would be. If you are even considering providing an asynchronous version of an operation to avoid blocking the thread, it is very likely that the operation is too expensive to be a property. In particular, operations that access the network or the file system (other than once for initialization) should most likely be methods, not properties.

The operation is a conversion, such as the Object.ToString method. The operation returns a different result each time it is called, even if the parameters didnt change. For example, the NewGuid method returns a different value each time it is called. The operation has a significant and observable side effect. Note that populating an internal cache is not generally considered an observable side effect. The operation returns a copy of an internal state (this does not include copies of value type objects returned on the stack).


Dont create a constructor that does not yield a fully initialized object Only create constructors that construct objects that are fully initialized. There shall be no need to set additional properties. A private constructor is exempt from this rule.


Dont return an array This allows calling code to change the items in the array. Even though callers cannot replace the array itself with another array, they can still replace an item within the array with another item. This may cause unexpected effects within the class that owns the array. Instead, return an IEnumerable<T>, or, if the number of items is important for the caller, an ICollection<T>.

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1026 Dont use readonly fields of arrays If you do, the array is read-only and cannot be changed, but the elements in the array can be changed. The following code example demonstrates how the elements of the read-only array countries can be changed. private readonly string[] countries = { Netherlands, Germany }; // Causes a compile error due to the readonly definition countries = new[] { Austria }; // Will compile and run happily, but was it intended?? countries[0] = France; AV1027 String and array properties should never return a null reference Returning null can be unexpected by the caller. The general rule is that null, an empty string (""), and an empty array (0 items) should be treated the same way. Always return an empty array and an empty string instead of a null reference. AV1030 Avoid using friend assemblies Using the [InternalsVisibleTo] attribute can lead to dirty hacks and bypassing basic OO principles. Do only use friend assemblies in well-known solution like the Memento design pattern or to grant unit test code access to certain internal members. AV1040 Provide a rich and meaningful exception message text The message should explain the cause of the exception and clearly describe what needs to be done to avoid the exception. AV1041 Do throw the most specific exception that is appropriate For example, if a method receives a null argument, it should throw ArgumentNullException instead of its base type ArgumentException. AV1042 Dont swallow errors by catching non-specific exceptions Avoid swallowing errors by catching non-specific exceptions, such as Exception, SystemException, and so on, in application code. There are cases when swallowing errors in applications is acceptable, but such cases are rare. An application should not swallow exceptions that can result in an unexpected or exploitable state. If you cannot predict all possible causes of an exception and ensure that malicious code cannot exploit the resulting application state, you should allow the application to terminate instead of swallowing the exception. AV1043 Prefer throwing existing exceptions Use existing exceptions residing in the System namespaces instead of creating custom exception types. AV1044 Avoid side-effects when throwing recoverable exceptions When you throw a recoverable exception, make sure that the object involved stays in a usable and predictable state. With usable it is meant that the caller can catch the exception, take any necessary actions, and continue to use the object again. With predictable is meant that the caller can make logical assumptions on the state of the object.

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

For instance, if during the process of adding a new item to a list, an exception is raised, then the caller may safely assume that the item has not been added, and another attempt to re-add it is possible. AV1050 Dont make assumptions on the objects state after raising an event Prepare for any changes to the current objects state while executing an event handler. The event handler may have called other methods or properties on you class that changed the objects state. AV1051 Do always check an event handler delegate for null An event that has no subscribers is null, so always make sure that the delegate is not null before invoking it. AV1052 Do use a protected virtual method to raise each event This is applicable only to non-static events on unsealed classes, not to structures, sealed classes, or static events. Complying with this guideline allows derived classes to handle a base class event by overriding the protected method. The name of the protected virtual method should be the same as the event name prefixed with On. For example, the protected virtual method for an event named TimeChanged is named OnTimeChanged.

Important Derived classes that override the protected virtual method are not required to call the base class implementation. The base class must continue to work correctly even if its implementation is not called. AV1053 Consider providing property-changed events Consider providing events that are raised when certain properties are changed. Such an event should be named PropertyChanged, where Property should be replaced with the name of the property with which this event is associated.

Note If your class has many properties that require corresponding events, consider implementing the INotifyPropertyChanged interface instead. AV1054 Dont pass null as the sender parameter when raising an event Often, an event handler is used to handle similar events from multiple senders. The sender argument is then used to get to the source of the event. Always pass a reference to the source (typically this) when raising the event. Furthermore dont pass null as the event data parameter when raising an event. If there is no event data, pass EventArgs.Empty instead of null.

Exception On static events, the sender parameter should be null. AV1060 Do only implement casts that operate on the complete object In other words, dont cast one type to another using a member of the source type. For example, a Button class has a string property Name. It is valid to cast the Button to the Control (since Button is a Control), but it is not valid to cast the Button to a string by returning the value of the Name property. AV1061 Dont generate a semantically different value with a cast For example, it is appropriate to convert a Time or TimeSpan into an Int32. The Int32 still represents the time or duration. It does not, however, make sense to convert a file name string such as c:\mybitmap.gif into a Bitmap object using a cast operation.

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1062 Avoid casting to and from System.Object in code that uses generics Use where contraints or the as operator instead. For example: class SomeClass {} // Don't class MyClass<T> { void SomeMethod(T t) { object temp = t; SomeClass obj = (SomeClass) temp; } } // Do class MyClass<T> where T : SomeClass { void SomeMethod(T t) { SomeClass obj = t; } } AV1070 Dont add extension methods to the same namespace as the extended class Even though it may seem convenient to add extension methods related to the String class in the System namespace, this may cause conflicts with future versions of the .NET Framework. AV1075 Adhere to the LINQ Design Guidelines for custom IQueryable implementations Developing a custom implementation of the IQueryable interface requires a great deal of background information on the .NET Framework and the Expression class hierarchy. Make sure you read the guidelines written down by Microsoft on this. See AV1076 Do evaluate the result of a LINQ expression before returning it Consider the following code snippet public IEnumerable<GoldMember> GetGoldMemberCustomers() { const decimal GoldMemberThresholdInEuro = 1000000; var q = from customer in db.Customers where customer.Balance > GoldMemberThresholdInEuro select new GoldMember(customer.Name, customer.Balance); return q; } Since LINQ queries use deferred execution, returning q will actually return the expression tree representing the above query. Each time the caller evaluates this result using a foreach or something similar, the entire query is re-executed resulting in new instances of GoldMember every time. Consequently, you cannot use the == operator to compare multiple GoldMember instances. Instead, always explicitly evaluate the result of a LINQ query using ToList(), ToArray() or similar methods.

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development


Maintainability Guidelines
Avoid using names that can be mistaken with other names. Although technically allowed, the following statement is quite confusing. bool b001 = (lo == l0) ? (I1 == 11) : (lOl != 101);


Do name assemblies after their contained namespace To allow storing assemblies in the Global Assembly Cache (GAC) the filename of an assembly must be unique. Therefore, use the namespace name as a prefix of the name of the assembly. As an example, consider a group of classes organized under the namespace AvivaSolutions.Web.Binding exposed by a certain assembly. According to this guideline, that assembly should be called AvivaSolutions.Web.Binding.dll. All DLLs should be named according to the pattern <Company>.<Component>.dll where <Company> refers to your companys name and <Component> contains one or more dot-separated clauses. For example AvivaSolutions.Web.Controls.dll.

Exception If you decide to combine classes from multiple unrelated namespaces into one assembly, consider post fixing the assembly with Core, but do not use that suffix in the namespaces. For instance, AvivaSolutions.Consulting.Core.dll. AV1506 Do name a source file to the class it contains Also, use Pascal casing for naming the file and dont use underscores. AV1507 Do limit the contents of a source code file to one class Exception It is allowed to place small helper classes such as the ones that provide event data (subclasses of EventArgs) in the same file as the corresponding main class. However, place them after the main class. AV1508 Do name a source file to the logical function of the partial type When using partial types and allocating a part per file, name each file after the logical part that part plays. For example: // In MyClass.cs public partial class MyClass {...} // In MyClass.Designer.cs public partial class MyClass {...} AV1510 Do use using instead of fully qualified type names Limit usage of fully qualified type names to prevent name clashing. For example: Dont: var list = new System.Collections.Generic.List<string>(); Do: using System.Collections.Generic; var list = new List<string>();

March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

If you do need to prevent name clashing, use a using directive to assign an alias: using Label = System.Web.UI.WebControls.Label; AV1515 Dont use "magic numbers" Dont use literal values, either numeric or strings, in your code other than to define symbolic constants. For example: public class Whatever { public static readonly Color PapayaWhip = new Color(0xFFEFD5); public const int MaxNumberOfWheels = 18; } Strings intended for logging or tracing are exempt from this rule. Literals are allowed when their meaning is clear from the context, and not subject to future changes, For example: mean = (a + b) / 2; WaitMilliseconds(waitTimeInSeconds * 1000); // okay // clear enough

If the value of one constant depends on the value of another, do attempt to make this explicit in the code. For example, dont public class SomeSpecialContainer { public const int MaxItems = 32; public const int HighWaterMark = 24; } but do public class SomeSpecialContainer { public const int MaxItems = 32; public const int HighWaterMark = 3 * MaxItems / 4; } Note An enumeration can often be used for certain types of symbolic constants. AV1520 Do use var only when the type is very obvious Only use var as the result of a LINQ query, or if the type is very obvious from the same statement and using it would improve readability.

// at 75%

// at 75%

Don't var i = 3; // var imyfoo = MyFactoryMethod.Create("arg"); // // // // what type? int? uint? float? Not obvious what base-class or interface to expect. Also difficult to refactor if you can't search for the class


March 2009 Dennis Doomen


C# 3.0 Coding Guidelines Guidelines for .NET Development

var q = from order in orders where order.Items > 10 and order.TotalValue > 1000; var repository = new RepositoryFactory.Get<IOrderRepository>(); var list = new ReadOnlyCollection<string>(); In all of three above examples it is clear what type to expect. AV1521 Do initialize variables at the point of declaration, if possible Avoid the C and Visual Basic styles where all variables have to be defined at the beginning of a block, but rather define and initialize each variable at the point where it is needed. AV1522 Do use constant fields for variables that will never change Making it const ensures that the same value is used consistently throughout your code, and it clarifies the exact meaning of the constant to other co-developers. The compiler inserts the values of const fields directly into the calling code, which means that const values can never be changed without the risk of introducing a compatibility issue. For example: private const int MaximumUsers = 100; Exception If the value of a constant field must be calculated at run-time (in the static constructor), use a static readonly field instead. AV1523 Favor Object and Collection Initializers over separate statements Instead of var startInfo = new ProcessStartInfo(myapp.exe); process.StandardOutput = Console.Output; process.UseShellExecute = true; Use Object Initializers var startInfo = new ProcessStartInfo(myapp.exe) { StandardOutput = Console.Output, UseShellExecute = true }; Similarly, instead of var countries = new List<string>(); countries.Add(Netherlands); countries.Add(United States); Use Collection Initializers var countries = new List<string> { Netherlands, United States }; Note Do not violate guideline AV1020 by not providing a proper parameterized constructor. AV1525 Dont make explicit comparisons to true or false It is usually bad style to compare a bool-type expression to true or false. For example: while while while while (condition == false) (condition != true) (((condition == true) == true) == true) (condition) // // // // wrong; bad style also wrong where do you stop? OK

March 2009 Dennis Doomen

[ 10 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1526 Do use an enumeration instead of a list of strings if the list of values is finite If a variable can have a limited set of constant string values, use an enumeration for defining the valid values. Using the enumeration instead of a constant string allows compile-time checking and prevents typos. AV1530 Dont change a loop variable inside a for loop block Updating the loop variable within the loop body is generally considered confusing, even more so if the loop variable is modified in more than one place. Although this rule also applies to foreach loops, an enumerator will typically detect changes to the collection the foreach loop is iteration over. for (int index = 0; index < 10; ++index) { if (some condition) { index = 11; // Wrong! Use break or continue instead. } } AV1531 Do update loop variables close to where the loop condition is checked This makes understanding the loop much easier. int index = 100; bool continueLoop = false; do { // Put your loop logic here // Keep these two lines close to the while statement. continueLoop = check if some condition is still met. --index; } while ((index > 0) && (continueLoop)) AV1535 Do use a block with all flow control keywords, even if it is empty Please note that this also avoids possible confusion in statements of the form: if (b1) if (b2) Foo(); else Bar(); // The right way: if (b1) { if (b2) { Foo(); } else { Bar(); } } Always surround the statements if, else, do, while, for and foreach, with a { and a }, even though the language does not require it. // which if goes with the else?

March 2009 Dennis Doomen

[ 11 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1536 Do add a default block after the last case in a switch statement Add a descriptive comment if the default block is supposed to be empty. Moreover, if that block is not supposed to be reached throw an InvalidOperationException to detect future changes that may fall through the existing cases. This ensures better code, because all paths the code can travel has been thought about. void Foo(string answer) { switch (answer) { case "no": Console.WriteLine("You answered with No"); break; case "yes": Console.WriteLine("You answered with Yes"); break; default: // Not supposed to end up here. throw new InvalidOperationException("Unexpected answer: " + answer); } } AV1537 Do code every if-else if statement with an else-part The intention of this rule, which applies to else-if constructs, is the same as the previous rule. For example. void Foo(string answer) { if (answer == "no") { Console.WriteLine("You answered with No"); } else if (answer == "yes") { Console.WriteLine("You answered with Yes"); } else { // What should happen when this point is reached? Ignored? If not, // throw an InvalidOperationException. } } AV1540 Avoid multiple return statements One entry, one exit is a sound principle and keeps control flow readable.

Exception In some cases, such as when preconditions are checked and that condition is not met, it may be good practice to exit a method immediately. AV1545 Dont use selection statements instead of a simple assignment or initialization Express your intentions directly. For example, rather than bool pos; if (val > 0) { pos = true; } else

March 2009 Dennis Doomen

[ 12 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

{ pos = false; } write bool pos = (val > 0); // initialization AV1546 Prefer conditional statements instead of simple if-else constructs For example, instead of string result; if (someString != null) { result = someString; } else { result = Unavailable; } return result;

write return someString ?? Unavailable; AV1550 Do explicitly define the scope of a type or member Even though types and members have a default scope, always explicitly define whether the scope is public, private or internal. For example: class Cat {} // Better: same visibility as Cat but more explicit internal class Dog { int length; // Better: same scope as length, but more explicit private int height; } AV1551 Do implement the most complete overload of a method or constructor and call it from the other overloaded

methods or constructors This guideline only applies to overloads that are intended for providing optional arguments. Consider for example the following code snippet: public class MyString { private string someText; public MyString(string s) { this.someText = s; } public int IndexOf(string s) {

March 2009 Dennis Doomen

[ 13 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

return IndexOf(s, 0, someText.Length); } public int IndexOf(string s, int startIndex) { return IndexOf(s, startIndex, someText.Length - startIndex ); } public int IndexOf(string s, int startIndex, int count) { return someText.IndexOf(s, startIndex, count); } } The class MyString provides three overloads for the IndexOf method, but two of them simply call the one with the most arguments. Notice that the same rule applies to class constructors; implement the most complete overload and call that one from the other overloads using the this() operator.

Important If you also want to allow derived classes to override these methods, define the most complete overload as a protected virtual method that is called by all overloads. public class MyString { // same as above public int IndexOf(string s, int startIndex, int count) { return InternalIndexOf(s, startIndex, count); } protected virtual int InternalIndexOf(string s, int startIndex, int count) { return someText.IndexOf(s, startIndex, count); } } AV1560 Do be consistent in the ordering of parameters in overloaded members Parameters with the same name should appear in the same position in all overloads. AV1561 Avoid methods with more than 5 arguments If you end up with a method with more than five arguments, use a structure or class for passing multiple arguments. Moreover, a method with that many arguments may imply that the responsibilities have not been evenly distributed over the classes in a component. AV1562 Dont use ref or out parameters Ref and out parameters make code less understandable and therefore may introduce bugs. Prefer returning compound objects instead. AV1570 Do always check the result of an as operation If you use as to obtain a certain interface reference from an object, always ensure that this operation does not return null. Failure to do so may cause a NullReferenceException at a much later stage if the object did not implement that interface.

March 2009 Dennis Doomen

[ 14 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development


Naming Guidelines
Do use proper US-English All identifiers should be named using words from the English language.

Choose easily readable identifier names. For example, HorizontalAlignment is more readable than AlignmentHorizontal. Favor readability over brevity. The property name CanScrollHorizontally is better than ScrollableX (an obscure reference to the X-axis). Avoid using identifiers that conflict with keywords of widely used programming languages.

Exception In some languages it may appear counterintuitive to translate domain-specific non-English terms into its English counterparts. In those cases, it may be wise to keep the original term from the native language. For instance, GetZaak for getting a legal case. However, Code Analysis also performs a spelling check, so you may need to add those terms to a Custom Code Analysis Dictionary. AV1705 Dont prefix member fields Dont use a prefix for field names. For example, Dont use g_ or s_ to distinguish static versus non-static fields. In general, a method in which it is difficult to distinguish local variables from member fields, is too big. Examples of incorrect identifier names are: _currentUser, mUserName, m_loginTime. AV1706 Do use abbreviations with care Dont use abbreviations or acronyms as parts of identifier names. For example, use OnButtonClick rather than OnBtnClick. Avoid single character variable names, such as i or t. Use index or temp instead.

Exceptions Use well-known abbreviations that are widely accepted such as UI instead of UserInterface. AV1707 Do name an identifier according its meaning and not its type

Do use semantically interesting names rather than language-specific keywords for type names. For example, GetLength is a better name than GetInt. Dont use terms like Enum, Class or Struct in a name. Do use a generic Common Type System (CTS) type name, rather than a language-specific name in the rare cases when an identifier has no semantic meaning beyond its type. For example, a method that converts data to Int16 should be named ToInt16, not ToShort because Short is the language-specific type name for Int16.


Identifiers that refer to an array or collection should have a plural name.

Do name classes, interfaces and value types with nouns, noun phrases or adjective phrases Do name classes, interfaces, and value types with nouns, noun phrases, or occasional adjective phrases, and dont give class names a prefix (such as the letter C).

Bad examples: SearchExamination: in this case it was a page for searching for examinations Common: does not end with a noun,and does not explain what its purpose is

March 2009 Dennis Doomen

[ 15 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

SiteSecurity: although the name is technically okay, it does not say anything about its purpose

Good examples: BusinessBinder, SmartTextBox, or EditableSingleCustomer.


Do name generic type parameters with descriptive names The following guidelines cover selecting the correct names for generic type parameters.

Do name generic type parameters with descriptive names, unless a single-letter name is completely self explanatory and a descriptive name would not add value. For example: IDictionary is an example of an interface that follows this guideline.

Use the letter T as the type parameter name for types with one single-letter type parameter. Do prefix descriptive type parameter names with the letter T. Consider indicating constraints placed on a type parameter in the name of parameter. For example, a parameter constrained to ISession may be called TSession.


Dont repeat the name of a class or enumeration in its members class Employee { // Wrong! static GetEmployee() {} DeleteEmployee() {} // Right static Get() {...} Delete() {...} // Also correct. AddNewJob() {...} RegisterForMeeting() {...} }


Do name members similarly to members of .NET Framework classes Stay close to the naming philosophy of the .NET Framework. Developers are already accustomed to the naming patterns .NET Framework classes use, so following this same pattern helps them find their way in your classes as well. For instance, if you define a class that behaves like a collection, provide members like Add, Remove and Count instead of AddItem, Delete or NumberOfItems.


Do properly name properties

Do name properties with nouns, noun phrases, or occasionally adjective phrases. Do name boolean properties with an affirmative phrase. E.g. CanSeek instead of CantSeek. Consider prefixing Boolean properties with Is, Has, Can, Allows, or Supports. Consider giving a property the same name as its type. When you have a property that is strongly typed to an enumeration, the name of the property can be the same as the name of the enumeration. For example, if you have an enumeration named CacheLevel, a property that returns one of its values can also be named CacheLevel.

March 2009 Dennis Doomen

[ 16 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1720 Do name methods using verb-object pair Name methods using a verb-object pair, such as ShowDialog. A good name should give a hint on the what of a member, and if possible, the why. interface IEmployeeRepository { Employee[] First() { } Employee[] GetFirstFive() {} Employee[] GetFiveMostRecent(){} void Add(Employee employee) {} // the } AV1725

// Wrong: What does first mean? How many? // Better // Best: self-describing // Although not using verb-object pair; type name is clear enough

Do name namespaces according a well-defined pattern All namespaces should be named according to the pattern <Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>] For instance: Microsoft.WindowsMobile.DirectX. Note Dont use the same name for a namespace and a type in that namespace. For example, dont use Debug for a namespace name and also provide a class named Debug in the same namespace.


Do add the suffix Callback to delegates related to callback methods Delegates that are used to refer to a callback method (so not an event) must be suffixed with Callback. For example: public delegate void AsyncIOFinishedCallback(IpcClient client, string message);


Do use a verb or verb phrase to name an event Do name events with a verb or a verb phrase. For example: Click, Deleted, Closing, Minimizing, and Arriving. For example, the declaration of the Search event may look like this: public event SearchEventHandler Search;

AV1736 AV1737

Dont add an Event suffix to the name of an event Do use -ing and -ed to express pre-events and post-events Do give event names a concept of before and after, using the present and past tense. For example, a close event that is raised before a window is closed would be called Closing and one that is raised after the window is closed would be called Closed. Dont use Before or After prefixes or suffixes to indicate pre and post events. Suppose you want to define events related to the deletion process of an object. Avoid defining the Deleting and Deleted events as BeginDelete and EndDelete.

Do define those events as follows:

Deleting: Occurs just before the object is getting deleted Delete: Occurs when the object needs to be deleted by the event handler. Deleted: Occurs when the object is already deleted.

March 2009 Dennis Doomen

[ 17 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV1738 Do prefix an event handler with On It is good practice to prefix the method that handles an event with On. For example, a method that handles the Closing event could be named OnClosing.

Exception In some situations you might be faced with multiple classes exposing the same event name. To allow separate event handlers use a more intuitive name for the event handler, as long as it is prefixed with On. AV1745 Group extension methods in a class suffixed with Extensions If the name of an extension method conflicts with another member or extension method, you must prefix the call with the class name. Having them in a dedicated class with the Extensions suffix improves readability.

March 2009 Dennis Doomen

[ 18 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development


Performance Guidelines
Clearly document if calling a member has a performance impact If calling a member causes a performance impact such as involvement of unmanaged code, copies that are being made, expensive calculations that are being performed, or network interaction, then clearly document that. This allows to caller to explicitly cache the result of calling the member and prevent a potential performance issue.

March 2009 Dennis Doomen

[ 19 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development


Usage Guidelines
Do use C# types instead of the types from the System namespace For example: use object instead of Object, string instead of String, and int instead of Int32.


Do properly name and use resources The guidelines in this topic apply to localizable resources such as error messages and menu text. Do use Pascal casing in resource keys. Do provide descriptive rather than short identifiers. Keep them concise where possible, but dont sacrifice readability. Do use only alphanumeric characters in naming resources.


Dont hardcode strings that are presented to end-users Use resources instead.


Dont hardcode strings that change based on the deployment Examples include connection strings, server addresses, etc. Use Resources, the ConnectionStrings property of the ConfigurationManager class, or the Settings class generated by Visual Studio.


Do build with the highest warning level Configure the development environment to use Warning Level 4 for the C# compiler, and enable the option Treat warnings as errors. This allows the compiler to enforce the highest possible code quality.

AV2211 AV2215

Avoid suppressing specific compiler warnings Do properly fill the attributes of the AssemblyInfo.cs file Ensure that the attributes for the company name, description, copyright statement, version, etc. are filled. One way to ensure that version and other fields that are common to all assemblies have the same values, is to move the corresponding attributes out of the AssemblyInfo.cs into a SolutionInfo.cs file that is shared by all projects within the solution.


Do always sign assemblies with a private key Signing an assembly with a private key will give the assembly a strong name which enables the following benefits.


Malicious attempts to replace the assembly with another equally named assembly will fail. Signed assemblies properly integrate with .NET security. They can be deployed in the Global Assembly Cache. Classes exposed in the assembly can be exposed to COM.

Avoid LINQ for simple expressions Rather than var q = from item in items where item.Length > 0; prefer using the extension methods from the System.Linq namespace. var q = items.Where(i => i.Length > 0);

March 2009 Dennis Doomen

[ 20 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

Since LINQ queries should be written out over multiple lines for readability, the second example is a bit more readable. AV2221 Do use Lambda expressions instead of delegates Lambda expressions have been introduced in C# 3.0 and provide a much more elegant alternative for anonymous delegates. So instead of Customer c = Array.Find(customers, delegate(Customer c) { return c.Name == Tom; }); use an Lambda expression: Customer c = Array.Find(customers, c => c.Name == Tom); Or even better var customer = customers.Where(c => c.Name == Tom);

March 2009 Dennis Doomen

[ 21 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV2301 AV2305

Documentation Guidelines
Do write comments and documentation in US English Do use XML tags for documenting types and members Document all public types and member of types using the built-in XML comment functionality of Visual Studio. Documenting your code allows Visual Studio to pop-up the documentation when your class is used somewhere else. Furthermore, by properly documenting your classes, tools can generate professionally looking class documentation.

The XML elements in the following table are available for documenting a class or class member.

XML element <summary> <remarks> <param> <returns> <typeparam> <value>

Description Short description of maximum two or three lines. This element is used to generate an overview page of the members of a class. Provides additional details, including preconditions, special behaviour, the relation to other members or classes. Describes the meaning of a method or constructor argument. Describes the return value of a method. Describes a type parameter for a generic type or method declaration to describe. Add a tag for each type parameter of the generic type or method. Describes the type of the data a property accepts or returns.

These elements can also be used on classes and their members but are used to enrich the documentation.

XML element <code> <example>

Description Marks a block of text as code. Specifies an example of how to use a method or other library member. This commonly involves using the <code> tag.

<seealso> <overloads> <event> <exception> <exclude/> <include>

Adds an entry to the See Also section at the bottom of a documentation page. Provides a summary for multiple overloads of a method. Without this, the overview page of a class will take the summary of the first overload. Indicates which events under which conditions will be raised by a method or property. Specifies which exceptions can be thrown that a caller may catch. Ensures that a member does not appear in generated documentation. Specifies to comments in another file that describe the types and members in your source code. This is an alternative to placing documentation comments directly in your source code file.

<permission> <preliminary> <threadsafety>

Documents the access of a member. Indicates that the documentation is preliminary and may change in the near future. Describes how a class behaves in a multi-threaded environment.

Inline elements can be used within the contents of the elements from the preceding table.

March 2009 Dennis Doomen

[ 22 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

XML element <see> <paramref> <typeparamref> <note> AV2306 Description Creates a hyperlink to another member or type. Creates a reference to a <param> of the current member. Creates a reference to a <typeparam> of the current member. Creates a note block with distinct appearance.

Do write XML documentation with the caller in mind Write the documentation of your class with the class user in mind. Assume the user will not have access to the source code and try to explain how to get the most out of the functionality of your class.


Do write MSDN-style documentation Following the MSDN on-line help style and word choice helps the developer to find its way through your documentation more easily. Tip The tool GhostDoc can generate a starting point for documenting code with a shortcut key.


Do document preconditions Properly document the preconditions for using a class or its members. Examples include:


Argument requirements: non-null, minimum length of an array, element type of an array, etc. State/order related: what other members must be called first. External dependencies: is a certain resource (network, file, etc) required?

Do document post conditions Document clearly whether a member returns null, an empty string, an empty array or something alike. To prevent surprises for the developer, try to stay close to the .NET Framework philosophy.


Do document the exceptions that a member can throw Document the exceptions a member can throw (using the <exception> tag) and explain under which situations it may throw this exception. Consider the .NET Framework online help as a good example of how to properly document this.

AV2315 AV2316

Do use // for comments Do write comments that explain the purpose of a code block Try to focus comments on the why and what of a code block and not the how. Avoid explaining the statements in words, but instead, help the reader understand why you chose a certain solution or algorithm and what you are trying to achieve. If applicable, also mention that you chose an alternative solution because you ran into a problem with the obvious solution.

Tip You can also define your own tags like <comment>. They will not be used yet, but can be helpful to add additional comments.

March 2009 Dennis Doomen

[ 23 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

AV2401 AV2402

Layout Guidelines
Dont put a using statement in a namespace Do order and group namespaces according the company // Microsoft namespaces are first using System; using System.Collections; using System.XML; // Then any other namespaces in alphabetic order using AvivaSolutions.Business; using AvivaSolutions.Standard; using Telerik.WebControls; using Telerik.Ajax;


Dont define multiple namespaces in one file A single file should contribute types to only a single namespace.


Do place modifiers in a well-defined order When multiple modifier keywords are needed in a type or member declaration, the modifiers should be placed in the following order of appearance: public, protected, internal, private, partial, new, abstract, virtual, override, sealed, static, readonly, extern, volatile, const.


Order class members in a well-defined pattern. Maintaining a common order allows other team members to find their way in your code more easily. In order of appearance:

1. Private fields (in a region) 2. Public read-only static fields 3. Constructors and the Finalizer 4. Events 5. Properties 6. Other members grouped in a functional manner. Common groups include: a. Control event handlers b. Page lifecycle handlers c.
Interface implementations (in a #region)

7. Private properties
Private methods should be placed behind the public member in calling order. This prevents readers from having to browse up and down through the code file. AV2407 Be reluctant with #regions Regions can be helpful, but can also hide to main purpose of a class. Therefore, use #regions only for:

Private fields (preferably in a Private Definitions region). Control event handlers Page lifecycle handlers

March 2009 Dennis Doomen

[ 24 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

Nested classes Helper classes (in the same file) Interface implementations (only if the class contains other members)

Although not required, give the #endregion statement the same name as the #region to improve readability. AV2410 Use empty lines wherever considered appropriate See an empty line as a paragraph break in a text document. So statements or declarations that logically belong to each other should be hold together. And remember, a text document with a paragraph break after each one or two sentences is difficult to follow, so dont overdo. Good candidates for an empty line include:

AV2411 AV2412 AV2413

Between members After the closing parentheses Between unrelated code blocks Around the #region keyword Between the using statements of the same company.

Dont exceed a line length of 130 characters Do insert space after if, switch, while, for, foreach, catch, lock and using Do put parentheses on a new line Always put { and } on new lines at the same level of indentation as the keyword they belong to. if (someCondition) { Foo(); } Exception To help distinct simple from more complex code, property getters and setters that only consist of a single statement may be written in a more compact form. For example: public string Name { get { return name; } set { if ((name != null) && (name.Length > 0)) { name = value; } } }

March 2009 Dennis Doomen

[ 25 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

1. LINQ Design Guidelines, Mircea Trofin

2. .NET Framework Design Guidelines, Brad Adams

3. Applying Domain-Driven Design and Patterns in C#, Jimmy Nielsen

4. The Developer Highway Code, Microsoft


6. Patterns & Practices guidance, Microsoft

7. Liskop Substitution Principle

March 2009 Dennis Doomen

[ 26 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development


List of Code Analysis Rules

The table below lists the Visual Studio Code Analysis / FxCop rules that we at Aviva Solutions recommend for any serious software development. Since generic and framework code requires a higher quality than for instance line-of-business applications, we made a distinction between the two using the LOB and Fx (framework) columns.
Design Rules CA1000 DoNotDeclareStaticMembersOnGenericTypes CA1001 TypesThatOwnDisposableFieldsShouldBeDisposable CA1002 DoNotExposeGenericLists CA1003 UseGenericEventHandlerInstances CA1004 GenericMethodsShouldProvideTypeParameter CA1005 AvoidExcessiveParametersOnGenericTypes CA1006 DoNotNestGenericTypesInMemberSignatures CA1007 UseGenericsWhereAppropriate CA1008 EnumsShouldHaveZeroValue CA1009 DeclareEventHandlersCorrectly CA1010 CollectionsShouldImplementGenericInterface CA1011 ConsiderPassingBaseTypesAsParameters CA1012 CA1013 CA1014 CA1016 CA1017 CA1018 CA1019 CA1020 CA1021 CA1023 CA1024 CA1025 CA1026 CA1027 CA1028 CA1030 CA1031 CA1032 CA1033 CA1034 CA1035 CA1036 CA1038 CA1039 CA1040 CA1041 CA1043 CA1044 CA1045 CA1046 CA1047 CA1048 CA1049 CA1050 CA1051 CA1052 CA1053 CA1054 CA1055 CA1056 CA1057 CA1058 CA1059 CA1060 CA1061 CA1062 CA1063 CA1064 AbstractTypesShouldNotHaveConstructors OverloadOperatorEqualsOnOverloadingAddAndSubtract MarkAssembliesWithClsCompliant MarkAssembliesWithAssemblyVersion MarkAssembliesWithComVisible MarkAttributesWithAttributeUsage DefineAccessorsForAttributeArguments AvoidNamespacesWithFewTypes AvoidOutParameters IndexersShouldNotBeMultidimensional UsePropertiesWhereAppropriate ReplaceRepetitiveArgumentsWithParamsArray DefaultParametersShouldNotBeUsed MarkEnumsWithFlags EnumStorageShouldBeInt32 UseEventsWhereAppropriate DoNotCatchGeneralExceptionTypes ImplementStandardExceptionConstructors InterfaceMethodsShouldBeCallableByChildTypes NestedTypesShouldNotBeVisible ICollectionImplementationsHaveStronglyTypedMembers OverrideMethodsOnComparableTypes EnumeratorsShouldBeStronglyTyped ListsAreStronglyTyped AvoidEmptyInterfaces ProvideObsoleteAttributeMessage UseIntegralOrStringArgumentForIndexers PropertiesShouldNotBeWriteOnly DoNotPassTypesByReference DoNotOverloadOperatorEqualsOnReferenceTypes DoNotDeclareProtectedMembersInSealedTypes DoNotDeclareVirtualMembersInSealedTypes TypesThatOwnNativeResourcesShouldBeDisposable DeclareTypesInNamespaces DoNotDeclareVisibleInstanceFields StaticHolderTypesShouldBeSealed StaticHolderTypesShouldNotHaveConstructors UriParametersShouldNotBeStrings UriReturnValuesShouldNotBeStrings UriPropertiesShouldNotBeStrings StringUriOverloadsCallSystemUriOverloads TypesShouldNotExtendCertainBaseTypes MembersShouldNotExposeCertainConcreteTypes MovePInvokesToNativeMethodsClass DoNotHideBaseClassMethods ValidateArgumentsOfPublicMethods ImplementIDisposableCorrectly ExceptionsShouldBePublic LOB x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x Fx x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x Notes

Factory methods always violate this rule

Often needs overruling if you want to enfore a specific subtype

Required to guarantee compliance with VB.NET

March 2009 Dennis Doomen

[ 27 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

CA1065 DoNotRaiseExceptionsInUnexpectedLocations Globalization Rules CA1300 SpecifyMessageBoxOptions CA1301 AvoidDuplicateAccelerators CA1302 DoNotHardcodeLocaleSpecificStrings CA1304 SpecifyCultureInfo CA1305 SpecifyIFormatProvider CA1306 SetLocaleForDataTypes CA1307 SpecifyStringComparison CA1308 NormalizeStringsToUppercase CA1309 UseOrdinalStringComparison Interoperability Rules CA1400 PInvokeEntryPointsShouldExist CA1401 PInvokesShouldNotBeVisible CA1402 AvoidOverloadsInComVisibleInterfaces CA1403 AutoLayoutTypesShouldNotBeComVisible CA1404 CallGetLastErrorImmediatelyAfterPInvoke CA1405 ComVisibleTypeBaseTypesShouldBeComVisible CA1406 AvoidInt64ArgumentsForVB6Clients CA1407 AvoidStaticMembersInComVisibleTypes CA1408 DoNotUseAutoDualClassInterfaceType CA1409 ComVisibleTypesShouldBeCreatable CA1410 ComRegistrationMethodsShouldBeMatched CA1411 ComRegistrationMethodsShouldNotBeVisible CA1412 MarkComSourceInterfacesAsIDispatch CA1413 AvoidNonpublicFieldsInComVisibleValueTypes CA1414 MarkBooleanPInvokeArgumentsWithMarshalAs CA1415 DeclarePInvokesCorrectly CA2101 SpecifyMarshalingForPInvokeStringArguments Portability Rules CA1900 ValueTypeFieldsShouldBePortable CA1901 PInvokeDeclarationsShouldBePortable Mobility Rules CA1600 DoNotUseIdleProcessPriority CA1601 DoNotUseTimersThatPreventPowerStateChanges Naming Rules CA1700 DoNotNameEnumValuesReserved CA1701 ResourceStringCompoundWordsShouldBeCasedCorrectly CA1702 CompoundWordsShouldBeCasedCorrectly CA1703 ResourceStringsShouldBeSpelledCorrectly CA1704 IdentifiersShouldBeSpelledCorrectly CA1705 LongAcronymsShouldBePascalCased CA1706 ShortAcronymsShouldBeUppercase CA1707 IdentifiersShouldNotContainUnderscores CA1708 IdentifiersShouldDifferByMoreThanCase CA1709 IdentifiersShouldBeCasedCorrectly CA1710 IdentifiersShouldHaveCorrectSuffix CA1711 IdentifiersShouldNotHaveIncorrectSuffix CA1712 DoNotPrefixEnumValuesWithTypeName CA1713 EventsShouldNotHaveBeforeOrAfterPrefix CA1714 FlagsEnumsShouldHavePluralNames CA1715 IdentifiersShouldHaveCorrectPrefix CA1716 IdentifiersShouldNotMatchKeywords CA1717 OnlyFlagsEnumsShouldHavePluralNames CA1718 AvoidLanguageSpecificTypeNamesInParameters CA1719 ParameterNamesShouldNotMatchMemberNames CA1720 AvoidTypeNamesInParameters/IdentifiersShouldNotContainTyp eNames CA1721 PropertyNamesShouldNotMatchGetMethods CA1722 IdentifiersShouldNotHaveIncorrectPrefix CA1724 TypeNamesShouldNotMatchNamespaces CA1725 ParameterNamesShouldMatchBaseDeclaration CA1726 UsePreferredTerms x x

o x x

o x x

Only if you need to handle right-to-left languages

o x x

o x x

DataSets should not be used anymore only if localization is important

o o o o o o o o o o o o o o o o o

o o o o o o o o o o o o o o o o o

Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke Only if you use P/Invoke

o o

o o

Only if you use P/Invoke Only if you use P/Invoke

x o

x o

x x x x x x x x x x x x x x x X X X X X X X X X X X

x x x x x x x x x x x x x x x x x x x x x x x x x x

March 2009 Dennis Doomen

[ 28 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

Performance Rules CA1800 DoNotCastUnnecessarily CA1801 ReviewUnusedParameters CA1802 UseLiteralsWhereAppropriate CA1804 RemoveUnusedLocals CA1805 DoNotInitializeUnnecessarily CA1806 DoNotIgnoreMethodResults CA1807 AvoidUnnecessaryStringCreation CA1809 AvoidExcessiveLocals CA1810 InitializeReferenceTypeStaticFieldsInline CA1811 AvoidUncalledPrivateCode CA1812 AvoidUninstantiatedInternalClasses CA1813 AvoidUnsealedAttributes CA1814 PreferJaggedArraysOverMultidimensional CA1815 OverrideEqualsAndOperatorEqualsOnValueTypes CA1816 DisposeMethodsShouldCallSuppressFinalize/CallGCSuppressFi nalizeCorrectly CA1817 DoNotCallPropertiesThatCloneValuesInLoops CA1818 DoNotConcatenateStringsInsideLoops CA1819 PropertiesShouldNotReturnArrays CA1820 TestForEmptyStringsUsingStringLength CA1821 RemoveEmptyFinalizers CA1822 MarkMembersAsStatic CA1823 AvoidUnusedPrivateFields CA1824 MarkAssembliesWithNeutralResourcesLanguage Security Rules CA2100 ReviewSqlQueriesForSecurityVulnerabilities CA2102 CatchNonClsCompliantExceptionsInGeneralHandlers CA2103 ReviewImperativeSecurity CA2104 DoNotDeclareReadOnlyMutableReferenceTypes CA2105 ArrayFieldsShouldNotBeReadOnly CA2106 SecureAsserts CA2107 ReviewDenyAndPermitOnlyUsage CA2108 ReviewDeclarativeSecurityOnValueTypes CA2109 ReviewVisibleEventHandlers CA2110 SecureGetObjectDataOverrides CA2111 PointersShouldNotBeVisible CA2112 SecuredTypesShouldNotExposeFields CA2114 MethodSecurityShouldBeASupersetOfType CA2115 CallGCKeepAliveWhenUsingNativeResources CA2116 AptcaMethodsShouldOnlyCallAptcaMethods CA2117 AptcaTypesShouldOnlyExtendAptcaBaseTypes CA2118 ReviewSuppressUnmanagedCodeSecurityUsage CA2119 SealMethodsThatSatisfyPrivateInterfaces CA2120 SecureSerializationConstructors CA2121 StaticConstructorsShouldBePrivate CA2122 DoNotIndirectlyExposeMethodsWithLinkDemands CA2123 OverrideLinkDemandsShouldBeIdenticalToBase CA2124 WrapVulnerableFinallyClausesInOuterTry CA2126 TypeLinkDemandsRequireInheritanceDemands CA2127 SecurityTransparentAssembliesShouldNotContainSecurity CriticalCode CA2128 SecurityTransparentCodeShouldNotAssert CA2129 SecurityTransparentCodeShouldNotReferenceNonpublicSecurity CriticalCode Usage Rules CA2200 RethrowToPreserveStackDetails CA2201 DoNotRaiseReservedExceptionTypes CA2202 DoNotDisposeObjectsMultipleTimes CA2204 LiteralsShouldBeSpelledCorrectly CA2205 UseManagedEquivalentsOfWin32Api CA2207 InitializeValueTypeStaticFieldsInline CA2208 InstantiateArgumentExceptionsCorrectly CA2210 AssembliesShouldHaveValidStrongNames CA2211 NonConstantFieldsShouldNotBeVisible CA2212 DoNotMarkServicedComponentsWithWebMethod CA2213 DisposableFieldsShouldBeDisposed CA2214 DoNotCallOverridableMethodsInConstructors CA2215 DisposeMethodsShouldCallBaseClassDispose


x x x x x x x x Far fetched x x x x x x x x x x x x x x


x x x x x x x x x o x x o x x x x x x x x x x x x x

Use a O/R Mapper instead


Only if you use P/Invoke

Only if you use P/Invoke


Is already checked by the compiler

x x x x x x x x x x x x x

x x x x x x x x x x x x x

Always violated by NHibernate entities

March 2009 Dennis Doomen

[ 29 ]

C# 3.0 Coding Guidelines Guidelines for .NET Development

CA2216 CA2217 CA2218 CA2219 CA2220 CA2221 CA2222 CA2223 CA2224 CA2225 CA2226 CA2227 CA2228 CA2229 CA2230 CA2231 CA2232 CA2233 CA2234 CA2235 CA2236 CA2237 CA2238 CA2239 CA2240 CA2241 CA2242 CA2243 DisposableTypesShouldDeclareFinalizer DoNotMarkEnumsWithFlags OverrideGetHashCodeOnOverridingEquals DoNotRaiseExceptionsInExceptionClauses6 FinalizersShouldCallBaseClassFinalizer FinalizersShouldBeProtected DoNotDecreaseInheritedMemberVisibility MembersShouldDifferByMoreThanReturnType OverrideEqualsOnOverloadingOperatorEquals OperatorOverloadsHaveNamedAlternates OperatorsShouldHaveSymmetricalOverloads CollectionPropertiesShouldBeReadOnly DoNotShipUnreleasedResourceFormats ImplementSerializationConstructors UseParamsForVariableArguments OverloadOperatorEqualsOnOverridingValueTypeEquals MarkWindowsFormsEntryPointsWithStaThread OperationsShouldNotOverflow PassSystemUriObjectsInsteadOfStrings MarkAllNonSerializableFields CallBaseClassMethodsOnISerializableTypes MarkISerializableTypesWithSerializable ImplementSerializationMethodsCorrectly ProvideDeserializationMethodsForOptionalFields ImplementISerializableCorrectly ProvideCorrectArgumentsToFormattingMethods TestForNaNCorrectly AttributeStringLiteralsShouldParseCorrectly x x x x x x x x x o x x x x x x x x x x x x x x x x x x x x x x x x x x x o x x x x x x x x x x x x x x x x x x

Is automatically done by the C# compiler Is automatically done by the C# compiler

Only if you target other languages than C# and VB.NET

Maintainability Rules CA1500 VariableNamesShouldNotMatchFieldNames CA1501 AvoidExcessiveInheritance CA1502 AvoidExcessiveComplexity CA1504 ReviewMisleadingFieldNames CA1505 AvoidUnmaintainableCode CA1506 AvoidExcessiveClassCoupling Reliability Rules CA2000 DisposeObjectsBeforeLosingScope CA2001 AvoidCallingProblematicMethods CA2002 DoNotLockOnObjectsWithWeakIdentity CA2003 DoNotTreatFibersAsThreads CA2004 RemoveCallsToGCKeepAlive CA2006 UseSafeHandleToEncapsulateNativeResources

x x x x x x

x x x x x x

x x x x x x

x x x x x x

March 2009 Dennis Doomen

[ 30 ]