En primer lugar: no hacer demasiado en un solo estado. Si tiene un gran número de operaciones de desreferenciación en una línea, va a ser mucho más difícil de encontrar al culpable. El Law of Demeter ayuda con esto también - si tiene algo como order.SalesClerk.Manager.Address.Street.Length
, entonces tiene muchas opciones que recorrer cuando obtiene una excepción. (Estoy no dogmática sobre la Ley de Demeter, pero todo con moderación ...)
En segundo lugar: Prefiero fundición sobre el uso de as
, a menos que sea válida para el objeto a ser un tipo diferente, que normalmente implica una verificación nula inmediatamente después. Así que aquí:
// What if foo is actually a Control, but we expect it to be String?
string text = foo as string;
// Several lines later
int length = text.Length; // Bang!
Aquí se conseguiría un NullReferenceException y, finalmente, lo cifran en text
siendo nula - pero entonces no sabría si eso es porque foo
era nula, o porque era un tipo inesperado. Si debe muy, muy ser un string
, a continuación, fundido en su lugar:
string text = (string) foo;
Ahora usted será capaz de notar la diferencia entre los dos escenarios.
En tercer lugar: como han dicho otros, valide sus datos, generalmente argumentos a API públicas y potencialmente internas. Hago esto en suficientes lugares en Noda Time que tengo una clase de utilidad para ayudarme a declutter el cheque. Así, por ejemplo (de Period
):
internal LocalInstant AddTo(LocalInstant localInstant,
CalendarSystem calendar, int scalar)
{
Preconditions.CheckNotNull(calendar, "calendar");
...
}
Usted debe documento lo que puede y no puede ser nulo, también.
Always 'Assert' generosamente para valores nulos. – leppie
@leppie - ¡eso es mucho afirmar! Sí, podría hacerlo, pero esperaba una solución más elegante para tener en cuenta situaciones como que me olvidé de hacer eso :) –
Protip: mantén tus métodos pequeños (digamos un máximo de 10-20 líneas), entonces realmente no necesitas números de línea . – leppie