fxCop

We use FxCop to check wether DelftShell sources follow correct coding standards such as

  • correct CapITalizaTION
  • exception throwing
  • naming

The reports are currently generated for core functionality only.

An fxcop report can be generated manually by running the fxcop project on Teamcity. To inspect the results we can use FxCopGraph and FxCopReport.

Common mistakes

Often I find people use System.Exception instead of a more specific one like ArgumentException or ReadOnlyException etc.
Assemblies are often missing the ClsCompliant attribute and SecurityPermission Attribute.

Example

[assembly: CLSCompliant(true)] //fxcop prerequisite
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)] //fxcop prerequisite

When using a format statement or a ToString() function, the CultureInfo is usually missing. At least specify CultureInfo.InvariantCulture so the conversion always yields the same result when intended:

String comparison:

  • String comparison for equality – Specify StringComparison.Ordinal or OrdinalIgnoreCase. This is true when comparing against string resources, and particularly important when comparing file names.
  • String comparison for sorting - Specify StringComparison.CurrentCulture when sorting lists
  • String.ToUpper - Use ToUpper rather than ToLower, and specify InvariantCulture in order to pick up OS casing rules
  • Determining BiDi languages, for example to load correct icons - Continue to specify CurrentUICulture for these cases.
  • String formatting including numbers, and int.ToString - Specify CurrentCulture
  • String formatting of strings only (no numbers) - the Culture arg here is a no-op. Use CurrentCulture.

examples:

myInt.ToString(CultureInfo.InvariantCulture)
string.Format(CultureInfo.InvariantCulture, "Tomorrow I will be {0} years old", 37)

Implementation of IDisposable is often incomplete. For classes that are not sealed you have to implement the Dispose Pattern. A codeproject article provides some details on how to implement IDisposable.

The public void Dispose() method should be left final (in other words, don't make this a virtual method) and should always look like this

public void Dispose()
{
    Dispose(true);
    GC.SupressFinalize(this);
}

All of your resource cleanup should be contained in the Dispose(bool disposing) method. If necessary, you should protect the cleanup by testing the disposing parameter. This should happen for both managed and unmanaged resources. The Dispose(bool disposing) runs in two distinct scenarios:

  • If disposing equals true, the method has been called directly or indirectly by a user's code. Managed and unmanaged resources can be disposed.
  • If disposing equals false, the method has been called by the runtime from inside the finalizer and you should not reference other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
    if (!disposed)
    {
        if (disposing)
        {
            // Dispose managed resources.
        }

        // There are no unmanaged resources to release, but
        // if we add them, they need to be released here.
    }
    disposed = true;

    // If it is available, make the call to the
    // base class's Dispose(Boolean) method
    base.Dispose(disposing);
}

Often people cast an object multiple times, leading to small performance degradation

if (myobject is IDataItem) //first cast
{
   node.Tag = ((IDataItem)myObject).Value; // second cast.
}

This can be done a bit more efficient in the following way:

IDataItem item
if ((item = myObject as IDataItem) != null) //first cast.
{
   node.Tag = item.Value;
}

I found the following links on internet about coding standards while fixing some issues:
document on coding standards
Exception throwing
Exception handling
FxCop, locale installatie
Using CultureInfo.InvariantCulture
Writing your own fxcop rules
When and how to dispose and finalize in c#
Why StringComparison.Ordinal is usually the right choice
New Recommendations for Using Strings in Microsoft .NET 2.0

  • No labels

1 Comment

  1. Unknown User (don)

    Thank for the info, good that someone checks it (smile).

    ... about exception handling I agree with principle Don't catch exceptions that you can't handle, or at least re-throw it. However during coding it feels much better when code is clean from all those try catch statements. In most we should try to avoid try catch where possible and use it only in exceptional situations - it will simplify our code a lot and will help developers read it.

    For development time I also added #if DEBUG around global Exception check in DelftShell.Loader since during development it is also very useful when exceptions are catched in VS and it jumps exactly to the place where it occurs.

    See also an interview with Anders Hejlsberg about Exceptions:

    ...
    Error handling you put somewhere else. Surely in any kind of event-driven application like any kind of modern UI, you typically put an exception handler around your main message pump, and you just handle exceptions as they fall out that way. But you make sure you protect yourself all the way out by deallocating any resources you've grabbed, and so forth. You clean up after yourself, so you're always in a consistent state. You don't want a program where in 100 different places you handle exceptions and pop up error dialogs. What if you want to change the way you put up that dialog box? That's just terrible. The exception handling should be centralized, and you should just protect yourself as the exceptions propagate out to the handler.
    ...

    So we can allow ourselves catching exceptions but only:

    • if there is no other way to fix it and global exception checker doe not work.
    • if we do something really very useful after catching it (write more informative message log, need to deallocate resources, re-throw with more information).