Do | Try to use descriptive parameter names to indicate the default used by shorter overloads. |
Avoid | Arbitrarily varying parameter names in overloads. |
Avoid | Being inconsistent in the ordering of parameters in overloaded members. |
Do | Make only the longest overload virtual (if extensibility is required). |
Do Not | Use ref or out modifiers to overload members. |
Do | Allow null to be passed for optional arguments. |
Do | Use member overloading rather than defining members with default arguments. |
Avoid | Implementing interface members explicitly without having a strong reason to do so. |
Consider | Implementing interface members explicitly, if the members are intended to be called only through the interface. |
Consider | Implementing interface members explicitly to simulate variance (change parameters or return type in “overridden” members). |
Consider | Implementing interface members explicitly to hide a member and add an equivalent member with a better name. |
Do Not | Use explicit members as a security boundary. |
Do | Provide a protected virtual member that offers the same functionality as the explicitly implemented member if the functionality is meant to be specialized by derived classes. |
Consider | Using a property, if the member represents a logical attribute of the type. |
Do | Use a property, rather than a method, if the value of the property is stored in the process memory and the property would just provide access to the value. |
Do | Use a method, rather than a property, when the operation: 1. Is an order of magnitude slower than field access. 2. Is a conversion operation (i.e., ToString()). 3. Returns a different result each time it is called (i.e., DateTime.Now()). 4. Has a significant noticeable side effect. 5. Returns a copy of an internal state. 6. Returns an array. |
Do | Create get-only properties if the caller should not be able to change the value of the property. |
Do Not | Provide set-only properties of properties with the setter having broader accessibility than the getter. |
Do | Provide sensible default values for all properties, ensuring that the defaults do not result in a security hole or terribly inefficient code. |
Do | Allow properties to be set in any order even if this results in a temporarily invalid state of the object. |
Do | Preserve the previous value if a property setter throws an exception. |
Avoid | Throwing exceptions from property getters. |
Consider | Using indexers to provide access to data stored in an internal array. |
Consider | Providing indexers on types representing collections of items. |
Avoid | Indexed properties with more than one parameter. |
Avoid | Indexers with parameter types other than System.Int32, System.Int64, System.String, System.Object, enum, or generic type parameters. |
Do | Use the name Item for indexed properties unless there is an obviously better name (e.g., see the Chars property on System.String). |
Do Not | Provide both an indexer and methods that are semantically equivalent. |
Do Not | Provide more than one family of overloaded indexers in one type. |
Do Not | Use non default indexed properties. |
Consider | Raising change notification events when property values in high-level APIs (usually designer components) are modified. |
Consider | Raising change notification events when the value of a property changes via external forces. |
Consider | Providing simple, ideally default constructors. |
Consider | Using a static factory method instead of a constructor if the semantics of the desired operation do not map directly to the construction of a new instance, or if following theconstructor design guidelines feels unnatural. |
Do | Use constructor parameters as shortcuts for setting main properties. |
Do | Use the same name for constructor parameters and a property, if the constructor parameters are used to simply set the property. |
Do | Minimal work in the constructor. |
Do | Throw exceptions from instance constructors if appropriate. |
Do | Explicitly declare the public default constructor in classes, if such constructor is required. |
Avoid | Explicitly defining default constructors on structs. |
Avoid | Calling virtual members on an object inside its constructor. |
Do | Make static constructors private. |
Do Not | Throw exceptions from static constructors. |
Consider | Initializing static fields inline rather than explicitly using static constructors, as the runtime is able to optimize the performance of types that don't have an explicitly defined static constructor. |
Do | Use the term “raise” for events rather than “fire” or “trigger”. |
Do | Use System.EventHandler<T> instead of manually creating new delegates to be used as event handlers. |
Consider | Using a subclass of EventArgs as the event argument, unless you are absolutely sure the event will never need to carry any data to the event handling method, in which case you can use the EventArgs type directly. |
Do | Use a protected virtual method to raise each event. |
Do | Take a parameter typed as the event argument class to the protected method that raises an event. |
Do Not | Pass null as the sender when raising a non static event. |
Do Not | Pass null as the event data parameter when raising an event (You should use EventArgs.Empty) |
Consider | Raising events that the end user can cancel. |
Do | Use a return type of void for event handlers. |
Do | Use object as the type of the first parameter of the event handler, and call it sender. |
Do | Use System.EventArgs or its subclass as the type of the second parameter of the event handler, and call it e. |
Do Not | Have more than two parameters on event handlers. |
Do Not | Provide instance fields that are public or protected. |
Do | Use constant fields for constants that will never change. |
Do | Use public static readonly fields for predefined object instances. |
Do Not | Assign instances of mutable types to readonly fields. |
Avoid | Defining operator overloads, except in types that should feel like primitive (built-in) types. |
Consider | Defining operator overloads in a type that should feel like a primitive type. |
Do | Define operator overloads in structs that represent numbers (such as System.Decimal). |
Do Not | Be cute when defining operator overloads. |
Do Not | Provide operator overloads unless at least one of the operands is of the type defining the overload. |
Do | Overload operators in a symmetric fashion. |
Consider | Providing methods with friendly names corresponding to each overloaded operator. |
Do Not | Provide a conversion operator if such conversion is not clearly expected by the end users. |
Do Not | Define conversion operators outside of a type's domain. |
Do Not | Provide an implicit conversion operator if the conversion is potentially lossy. |
Do Not | Throw exceptions from implicit casts. |
Do | Throw System.InvalidCastException if a call to a cast operator results in a lossy conversion and the contract of the operator does not allow lossy conversions. |
Do | Use the least derived parameter type that provides the functionality required by the member. |
Do Not | Use reserved parameters. |
Do Not | Have publicly exposed methods that take pointers, arrays of pointers, or multidimensional arrays as parameters. |
Do | Place all out parameters following all of the by-value and ref parameters (excluding parameter arrays), even if it results in an inconsistency in parameter ordering between overloads. |
Do | Be consistent in naming parameters when overriding members or implementing interface members. |
Do | Use enums if otherwise a member would have two or more Boolean parameters. |
Do Not | Use Booleans unless you are absolutely sure there will never be a need for more than two values. |
Consider | Using Booleans for constructor parameters that are truly two state values and are simply used to initialize Boolean properties. |
Do | Validate arguments passed to public, protected, or explicitly implemented members. |
Do | Throw ArgumentNullException if a null argument is passed but the member does not support null arguments. |
Do | Validate enum parameters. |
Do Not | Use Enum.IsDefined for enum range checks. |
Do | Be aware that mutable arguments passed might have changed after they were validated. |
Avoid | Using out or ref parameters. |
Do Not | Pass reference types by reference. |
Consider | Adding the params keyword to array parameters, if you expect the end users to pass arrays with a small number of elements. |
Avoid | Using params arrays if the caller would almost always have the input already in an array. |
Do Not | Use params arrays if the array is modified by the member taking the params array parameter. |
Consider | Using the params keyword in a simple overload, even if a more complex overload could not use it. |
Do | Try to order parameters to make it possible to use the params keyword. |
Consider | Providing special overloads and code paths for calls with a small number of arguments in extremely performance-sensitive APIs. |
Do | Be aware that null could be passed as a params array argument. |
Do Not | Use the varargs methods, otherwise known as the ellipsis. |
Do | Provide an alternative for any member that takes a pointer argument, as pointers are not CLS compliant. |
Avoid | Doing expensive argument checking of pointer arguments. |
Do | Follow common pointer-related conventions when designing members with pointers. |