Cada vez son más las herramientas disponibles para analizar un código fuente. Incluso la última versión del compilador de C# busca violaciones del principio de Liskov, aunque no lo califica como un error, sino como sólo un warning.
Visual Studio 2010 viene con una nueva característica de análisis de código que podemos usar para realizar un análisis más profundo y evitar que nos salten los colores cuando enseñamos un código de nuestra creación:

Incluso con estas herramientas podemos establecer y personalizar las reglas que queremos cumplir:

Estas herramientas nos ofrecen avisos sólo cuando se incumplen estas reglas, lo que no significa necesariamente que haya un bug, sino simplemente que pueda existir. Ante estos reportes siempre es mejor echar un vistazo al código y no dejar que las alarmas se conviertan en hechos por la ley de Murphy.
En cada proyecto donde queramos usar la herramienta tendremos que activarla explícitamente:

Veamos ahora un ejemplo de código que provocaría la alerta de esta herramienta en tiempo de compilación:
var numbers= new int[2];
numbers[3]=0;
Sin embargo, más útil puede resultarnos cuando la usamos con los contratos de código explícitos, con sus pre-condiciones y pos-condiciones. Veamos un pequeño ejemplo.
Supongamos que tenemos este código en alguno de nuestros métodos:
var idFactura= ObtenerUltimoId();
ProcesaFactura(idFactura);
A simple vista, ninguna herramienta de análisis estático haría nada con este código, a no ser que se le indicase algún tipo de información extra. Y aquí es donde entran los contratos. El código de la función ObtenerUltimoId() podría ser como este, si usamos contratos:
public int ObtenerUltimoId()
{
Contract.Ensures(Contract.Result<int>()>0);
....
return n;
}
Con los contratos se indica que el método tiene que devolver un valor mayor que cero. Esa información la usará el Checker para comprobar el código fuente.
Veamos ahora como podría ser el método ProcesaFactura():
public void ProcesaFactura(int idFactura)
{
Contract.Requires<ArgumentException>(idFactura>0);
.....
}
Bajo esa situación la herramienta Static Checker comprueba que un método tiene una condición de Requires y recibe datos de otro método, que no dice nada sobre lo que va a devolver. Esta sería la pantalla que nos mostraría el análisis:

Sobra decir que Static Checker se hace todavía más útil cuantos más contratos usemos.
Si el código heredado no tiene contratos, se obtendrán algunos warnings molestos del Static Checker. Sin embargo, la API de Code Contracts ofrece un pequeño workarround sobre esto.
Básicamente, este tipo de warnings son debidos a la falta de información, es decir, el Checker no es capaz de encontrar la información necesaria. Sin embargo, podemos observar algunos detalles en el siguiente código:

El checker nos avisa de una posible referencia nula. Aparentemente la variable context está siendo usada sin haber sido inicializada previamente. ¿Quién es el responsable del warning? ¿el Checker u otra cosa?
En este caso, el aviso lo está provocando ReSharper, cuyo motor de análisis identifica una posible referencia nula. ¿Pero porqué no nos lo da el Checker?, la respuesta es por la linea:
Contract.Assume(context!=null);
Con esa linea estamos diciendo al Checker que la variable context nunca va a ser nula. Gracias a ello el Checker confía en nosotros y añade esa información a sus procesos. Resharper no ofrece soporte completo a los contratos de .NET, de ahí el aviso. Sin embargo, ReSharper soporta su propio sistema de anotaciones que podéis usar de la misma manera. Para más información se puede consultar este artículo.
La primera es crear una configuración de compilación especial, y habilitamos únicamente las comprobaciones en ella. Compilamos en esa configuración de vez en cuando para obtener información, corregimos los posibles problemas y continuamos trabajando sin el análisis estático.
La segunda es probar a usar contratos poco a poco. Aplicamos contratos de manera extensiva en el código, pero deshabilitamos los contratos a nivel de assembly. Esto lo asemos añadiendo el siguiente atributo en las propiedades del assembly:
[assembly:ContractVerification(false)]
Lo siguiente, es re-habilitar la comprobación de contratos sólo cuando estemos centrados en clases, métodos o assemblies.
En los proyectos la complejidad aumenta continuamente y el equipo de desarrollo se va quedando sin tiempo. Integrar este tipo de herramientas ahorra algún tiempo de compilación, pero más importante todavía es que nos protege de errores feos en nuestro software.