With all the fuss about how important it is to create maintainable code, a huge issue that sparks numerous techno-religious debates is the idea that code should follow a specific naming convention. The main problem is summed up by the question: What naming convention should be used? There are a number of naming conventions documented for developers, but typically the answer is left to personal preference. However, Microsoft is pushing the idea of “best practice” for a number of areas of .NET development, including standardized coding conventions. A common problem with legacy Win32 API code is the variation among naming conventions. It is not uncommon to find two components in the API that use completely different conventions. However, Microsoft has enforced standards for the .NET Class Framework that define how code should be named and formatted. While you do not have to follow the proposed standard, it is recommended that you do so for consistency and to make your code easier to read by other .NET developers.
This chapter summarizes the standard coding conventions set forth by Microsoft that should be employed in your code. Keep in mind that you should still read the Microsoft Design Guidelines for Class Library Developers, but this chapter should be enough of a generalization to get you started.
The .NET class framework uses three types of capitalization styles, presented in Table 12.1.
Table 12.1. .NET Class Framework Capitalization Styles
Case Type | Description |
---|---|
Pascal Case | Make the first letter uppercase as well as the first letter of each subsequent word. All other letters remain lowercase. An example would be XmlSerializer. |
Camel Case | Identical to Pascal case, except the first letter is not uppercase. An example would be remotingEndpoint. |
Uppercase | Make all letters capitalized when an identifier consists of less than three letters. An example would be System.IO. |
There are different situations when a certain capitalization style is appropriate. The situations suitable for certain capitalization styles are presented in Table 12.2.
Table 12.2. Capitalization Style Situations
Situation | Appropriate Style | Notes |
---|---|---|
Class | Pascal Case |
|
Enum Type | Pascal Case |
|
Enum Value | Pascal Case |
|
Event | Pascal Case |
|
Exception Class | Pascal Case | Suffixed with Exception |
Read-Only Static Field | Pascal Case |
|
Interface | Pascal Case | Prefixed with I |
Method | Pascal Case |
|
Namespace | Pascal Case |
|
Parameter | Camel Case |
|
Property | Pascal Case |
|
Protected Instance Field | Camel Case | Better to use a property |
Public Instance Field | Pascal Case | Better to use a property |
When naming classes, the standard is to use Pascal case. Additionally, classes should be named using a noun or a noun phrase. Finally, never use an underscore in a class name either.
One traditional style common among many developers is to use prefixes such as cFileStream
or CFileStream
. Never use prefixes anywhere with the exception of interfaces. The proper naming would be FileStream
in this example.
Abbreviations should be used only when absolutely necessary. They cause confusion when reading code, and break from the standards used in the class framework.
Derived classes should be named in a compounded fashion where the second half of the name is the base class name. An example would be the derived class SystemException
, which inherits from the base class Exception
. This guideline is to be used at your discretion, as derived class names should only be compounded when it makes sense to do so.
Example:
public class SimpleException : Exception { }
When naming interfaces, the standard is to use Pascal case. Additionally, interfaces should be named using a noun or noun phrase, or an adjective that describes its behavior. Finally, never use an underscore in a class name either.
Interfaces should always be prefixed with I
, as in IBaseController
. This is the only situation where an identifier should be prefixed in the .NET class framework.
When a class implements an interface, the naming should only differ by the prefix I
on the interface name.
Abbreviations should be used only when absolutely necessary. They cause confusion when reading code, and break from the standards used in the .NET Class Framework.
public interface IBaseController { } public class BaseController : IBaseController { }
When naming namespaces, there are some common rules that should be followed for consistency. Use Pascal case, and separate all logical components with periods.
The typical formatting is as follows:
CompanyName.TechnologyName.Feature[.Design]
Design is an optional namespace path that can be used when you have design time code that you are separating from the feature code itself.
Prefixing the namespace with the company name helps to avoid type name conflicts with another company that’s possibly offering the same technology and features.
Additionally, types in a namespace should have dependencies to types in the containing namespace. For example, Wihlidal.Networking.DeadReckoning
would have dependencies to types in Wihlidal.Networking
.
Never use the same name for both a class and a namespace. For example, do not have the namespace Wihlidal.Utilities.Log
and have a contained class called Log
.
Lastly, just because a particular assembly uses the namespace Wihlidal.Networking.DeadReckoning
, it does not have to contain any code in the Wihlidal.Networking
namespace. It is perfectly acceptable and common to have multiple assemblies associated with a particular namespace.
Example:
Wihlidal.Networking.DeadReckoning
or
Wihlidal.Controls.InterfaceBuilder Wihlidal.Controls.InterfaceBuilder.Design
There are not a lot of guidelines for attribute naming, but be sure to use Pascal case. The only rule is to suffix the attribute type name with Attribute
.
Example:
InterfaceControlAttribute
When naming enumerations, the standard is to use Pascal case for both type and value identifiers.
Abbreviations should be used only when absolutely necessary. They cause confusion when reading code, and they break from the standards used in the class framework.
Never suffix an enumeration with Enum
. The identifier name should also be singular unless it is a bit field, in which case the name would be plural. Additionally, bit fields should always be marked with [FlagsAttribute]
.
Example:
public enum InterfaceColor { Red, Black, Yellow } [FlagsAttribute] public enum InterfaceColors : short { Red = 0, Black = 1, Yellow = 2 }
When naming static fields, the standard is to use Pascal case. Additionally, static fields should be named using a noun, noun phrase, or abbreviations of nouns. Lastly, never use Hungarian notation or any other sort of prefixes or suffixes.
It is “best practice” to use a static property instead of a static field whenever possible.
Example:
private static int MyStaticField;
When naming parameters, the standard is to use Camel case. Additionally, parameter names should be descriptive enough that their use should be evident by their name alone.
Use a parameter name that describes its meaning rather than its type. Use type-based names only when necessary.
Never use reserved parameters. These parameters are reserved for data that can be added in with a later version of a particular component, and storing your data in a reserved property can lead to issues with invalid data or software instability.
Never name parameters using Hungarian notation.
Example:
Type GetType(string typeName) string Format(string format, object[] args)
When naming methods, the standard is to use Pascal case. Additionally, method names should be named using verbs or verb phrases. Method names should be very descriptive, and the behavior of the method should be easily determined from the name alone.
Example:
GetInterfaceControl() ExecuteBatchProcess() InsertRecord()
When naming properties, the standard is to use Pascal case. Additionally, properties should be named using a noun or noun phrase, and never use Hungarian notation.
It is a good idea to name your properties the same name as the underlying types when applicable.
Example:
private Color backColor; public Color BackColor { get { return backColor; } set { backColor = value; } }
When naming events, the standard is to use Pascal case. Additionally, events should never have a prefix or a suffix, and never use Hungarian notation.
Events should be named with a verb such as Launched, Clicked, Closing, or Paint. Events in a pre-event context should be named with the -ing form of a verb, and events in a post-event context should be named with the past tense of a verb.
Event handlers should have an EventHandler
suffix. Additionally, event argument types should have an EventArgs
suffix.
Example:
public delegate void InterfaceControlEventHandler(object sender, InterfaceControlEventArgs e); public InterfaceControlEventHandler InterfaceControlClicked; public class InterfaceControlEventArgs : EventArgs { private InterfaceControl _selectedControl = null; public InterfaceControl SelectedControl { get { return _selectedControl; } } public InterfaceControlEventArgs(InterfaceControl selectedControl) { _selectedControl = selectedControl; } }
There are guidelines regarding abbreviations. Disregarding these guidelines can lead to issues with interoperability or general confusion about the purpose of a particular identifier.
Identifiers should not have contracted or abbreviated parts. Use SendReplyMessage
instead of SendReplyMsg
.
Acronyms should be formatted using either Pascal or Camel case when consisting of more than two letters. Never use acronyms that are not generally accepted or known in the computing world.
Use abbreviations to replace lengthy phrases, such as Http
instead of HyperTextTransferProtocol
.
Identifiers and parameters should not be abbreviated. If you must use abbreviations, then you should use Camel case when the abbreviated word consists of three or more letters.
The main focus of this chapter was to present an overview of the standardized coding conventions that Microsoft encourages .NET developers to adopt. This is in no way the full convention, but it is enough of a subset to show how code should be written in C#.NET. For more information, please review the Microsoft Design Guidelines for Class Library Developers located on MSDN.
18.119.235.79