-
Notifications
You must be signed in to change notification settings - Fork 0
Coding Standards: .NET Types and Type Members
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
✔️ It is RECOMMENDED to follow .NET Framework Design Guidelines article regarding this topic for whatever this document does not specify.
❌ Enumerations SHOULD NOT end with the words "Flags" or "Flag".
❌ Enumeration SHALL NOT have a name that ends with the words "Enum" or "Enumeration".
❌ Enumerations SHALL NOT have a only value.
An enumeration having only one value is against the purpose of the managed enumerations.
❌ Enumerations SHALL NOT have reserved values for future use.
Values can be added managed enumerations without breaking any compatiblity by JUST simply add them. There is no need for reserved values.
❌ The System.Enum
type MUST NOT be inherited directly.
Use the feature of your language for this, for example, the enum
keyword of C#. By inherting System.Enum
, you cannot define anything inside it; this class only provides methods for your enumeration to use, a few static methods related to and for the enumerations, and provide a basis for languages to implement the enumeration feature.
✔️ Interfaces MUST begin with the letter 'I'.
For example, IEnumerable
. This rule still applies even if the name itself begins with the letter 'I'. For example, IItem
.
❌ Exceptions SHOULD NOT devire from ApplicationException
.
The ApplicationException
is a legacy of an early concept of .NET Exceptions: exceptions in the CLR devires from SystemException
and exceptions created by application devires from ApplicationException
. However, this concept never worked, but ApplicationException
was kept for backward compatbility.
See this article for more information.
❌ Try-catch blocks MUST NOT catch ApplicationException
.
Any sort of ApplicationException
, whether techinical or non-techinical, contains sensitive information or not, could be devired from ApplicationException
(this means it is meaningless to catch this type). If you want to catch all exceptions, simply catch Exception
.
❌ Static classes SHOULD NOT be used for main logic.
Instead, use Singleton for the core logic.
❌ Records and structures SHOULD NOT be used in case of possiblity of regularily passed to 'object' variables, parameters, etc.
Doing so involves boxing and unboxing. Not only this operation is slow, it can negatively affect the heap, and thus performance.
❌ Records and structures SHOULD NOT be used to store anything that must be regularily modified.
For this purpose, use classes instead.
❌ Records and structures SHOULDD NOT be used to store large pieces of data.
Value types, like structures, are copied every time it is assigned to a different variable, etc.
❌ Parameters for one-line records MUST NOT have a name that is in camelCase.
The parameters for one-line records are actually property names.
✔️ Type members MUST be PascalCase unless specified otherwise by this document, or whenever interopablity or script integration requires so.
✔️ Events MAY use generic version of the EventHandler
type (EventHandler<T>
) for custom arguments.
✔️ Events with the default event handler is RECOMMENDED to use (EventArgs.Empty
) instead of creating a new EventArgs
instance for events with no arguments.
✔️ Event handlers are RECOMMENDED to use sender
for the sender of the event (the first parameter) and e
for the arguments (the second parameter).
❌ Event invokers MAY NOT trigger an event by calling them like a method. An event without at least one handler listening is considered null
by .NET, and triggering an event without any listener will result in NullReferenceException
.
Instead, use Event?.Invoke(sender, args)
with the Event
replaced by the name of the event.
❌ Properties SHOULD NOT be set-only.
Set-only properties are confusing, as developers tend to except that a property is get-able by default. Whenever there is a case when a value cannot be access and can only be mutated, use a mutator method that begins with the word Set
.
❌ Properties that only serves as a wrapper for a field without any custom behaviour are NOT RECOMMENDED.
Whenever a wrapper property should be replaced by auto-property, do it.
❌ Private, internal or otherwise non-public methods SHALL NOT use camelCase
for any reason.
Despite Google recommending this, this is not a good practice. Use PascalCase
just like every other methods.
✔️ Private fields SHALL be prefixed by an underscore (_
).
❌ Fields MAY NOT use Hungarian Notation.
❌ Declaring public, non-readonly
fields is NOT RECOMMENDED. Use a property instead.
✔️ Parameter names SHALL be in camelCase, regardless of the language.