C# Miscellaneous Design Standards · CS-11
Throw exceptions rather than returning some kind of status value · CS-11.1 · SHOULD
A code base that uses return values for reporting the success or failure tends to have nested if-statements sprinkled all over the code. Quite often, a caller forgets to check the return value anyhow. Structured exception handling has been introduced to allow you to throw exceptions and catch or replace exceptions at a higher layer. In most systems it is quite common to throw exceptions whenever an unexpected situations occurs.
Provide a rich and meaningful exception message text · CS-11.2 · MUST
The message should explain the cause of the exception and clearly describe what needs to be done to avoid the exception.
Throw the most specific exception that is appropriate · CS-11.3 · MUST
For example, if a method receives a null argument, it should throw ArgumentNullException instead of its base type ArgumentException.
Roslyn Analyzer Rule CA2201
Don't swallow errors by catching generic exceptions · CS-11.4 · MUST
Avoid swallowing errors by catching non-specific exceptions, such as Exception, SystemException, and so on, in application code. Only top-level code, such as a last-chance exception handler, should catch a non-specific exception for logging purposes and a graceful shutdown of the application.
Roslyn Analyzer Rule CA1031
Always check an event handler delegate for null · CS-11.5 · MUST
null · CS-11.5 · MUSTAn event that has no subscribers is null, so before invoking, always make sure that the delegate list represented by the event variable is not null. Furthermore, to prevent conflicting changes from concurrent threads, use a temporary variable to prevent concurrent changes to the delegate.
event EventHandler<NotifyEventArgs> Notify;
void RaiseNotifyEvent(NotifyEventArgs args)
{
EventHandler<NotifyEventArgs> handlers = Notify;
if (handlers != null)
{
handlers(this, args);
}
}You can prevent the delegate list from being empty altogether. Simply assign an empty delegate like this:
event EventHandler<NotifyEventArgs> Notify = delegate {};Use a protected virtual method to raise each event · CS-11.6 · SHOULD
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.
NOTE: 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.
Roslyn Analyzer Rule AV1225
Don't pass null as the sender argument when raising an event · CS-11.7 · MUST
null as the sender argument when raising an event · CS-11.7 · MUSTOften, 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 don’t 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 argument SHOULD be null.
Roslyn Analyzer Rule AV1235
Evaluate the result of a LINQ expression before returning it · CS-11.8 · MUST
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.
Roslyn Analyzer Rule AV1250
Use new() expressions · CS-11.9 · SHOULD
new() expressions · CS-11.9 · SHOULDUse target-typed new expressions to simplify object creation.
For example, rather than this:
var collection = new List<int>();prefer this:
List<int> collection = new();