2009-08-31 10 views
50

Estoy trabajando en un método que hace algo dado un parámetro de cadena. Un valor válido para el parámetro de cadena es cualquier cosa que no sea nulo o cadena. Vacío. Entonces mi código se ve así.¿Debo tirar ArgumentNullException si una cadena está en blanco?

 
private void SomeMethod(string someArgument) 
{ 
    if(string.IsNullOrEmpty(someArgument)) 
     throw new ArgumentNullException("someArgument"); 

    // do some work 
} 

Nada demasiado emocionante. Mi pregunta es, ¿está bien tirar una ArgumentNullException incluso si la cadena es igual a string.Empty? Porque técnicamente no es nulo. Si crees que no debería lanzar ArgumentNullException, ¿qué excepción debería arrojarse?

+1

Lanzar ArgumentNullException cuando la cadena es "" es engañosa. –

+0

Estoy de acuerdo, ay, la razón por la que lo he hecho de esta manera es por la respuesta que dio "Joe", se usa así en el código .net framework. – Kepboy

Respuesta

35

ArgumentException se debe lanzar para el caso String.Empty. Esto indicaría un problema que no sea nulo. Para evitar un NullReferenceException compruebo primero por nulo, luego recorte y verifico la caja vacía para evitar que pase espacio en blanco.

private void SomeMethod(string someArgument) 
{ 
    if(someArgument == null) 
     throw new ArgumentNullException("someArgument"); 

    if (someArgument.Trim() == String.Empty) 
     throw new ArgumentException("Input cannot be empty", "someArgument"); 

    // do some work 
} 

A partir de .NET 4.0 se puede utilizar el método String.IsNullOrWhiteSpace para llevar a cabo estos controles de una sola vez. Al hacerlo, renuncia a la posibilidad de especificar un tipo de excepción granular, por lo que optaría por el ArgumentException y actualizar el mensaje en consecuencia.

+0

Estoy usando C# 2.0, la única referencia a InvalidArgumentException está en el espacio de nombres Microsoft.SqlServer.Management.Common, ¿es lo que usted recomienda o está sugiriendo que cree mi propia clase InvalidArgumentException? – Kepboy

+0

@Keith: tienes razón, mi error. Podrías escribir el tuyo propio si lo deseas o usar ArgumentException provisto por el framework. Editaré para reflejar el nombre correcto. –

+3

El constructor ArgumentException no toma un parámetro "paramName" como ArgumentNullException. Así que 'throw new ArgumentException ("paramName")' es potencialmente confuso, ya que no da ninguna indicación de lo que está mal con el argumento. Debería proporcionar un argumento "mensaje" algo así como ("someArgument puede no ser una cadena vacía"). Y en una aplicación internacional, este mensaje debería estar localizado. Por lo tanto, solo abordaría todos estos problemas si realmente existe la necesidad de distinguir el caso nulo del caso de cadena vacía. – Joe

5

Debe arrojar un ArgumentException si una cadena vacía no es una entrada aceptada para su método. Puede ser muy confuso para los clientes si lanza un ArgumentNullException mientras que no proporcionaron un argumento null.

Es simplemente otro caso de uso. También puede tener métodos que no acepten valores de entrada nulos pero que acepten cadenas vacías. Es importante ser coherente en toda su aplicación.

+0

Estaba pensando a lo largo de las líneas de ArgumentOutOfRangeException, pero tal vez eso se utiliza para excepciones de rango de índice de matriz. – Kepboy

+0

Para excepciones de índice de matriz, se utiliza IndexOutOfRangeException. Debe usar ArgumentOutOfRangeException solo si su método está documentado para aceptar solo una colección específica de cadenas (p.: "abc", "def", "ghi" son las únicas entradas aceptadas). –

+0

Gracias por aclarar. – Kepboy

1

ArgumentNullException a veces se utiliza en .NET Framework para el caso String.IsNullOrEmpty - un ejemplo es System.Windows.Forms.Clipboard.SetText.

Así que creo que es razonable hacer lo mismo en su código, a menos que haya un valor real para distinguir los dos casos.

Tenga en cuenta que esta y otras excepciones derivadas de ArgumentException generalmente indican un error de programación y, por lo tanto, deben proporcionar la información necesaria para ayudar al desarrollador a diagnosticar el problema. Personalmente, creo que es poco probable que un desarrollador lo encuentre confuso si usa ArgumentNullException para un argumento de cadena vacío, especialmente si documenta este comportamiento como en el siguiente ejemplo.

/// <summary> 
/// ... description of method ... 
/// </summary> 
/// <param name="someArgument">... description ...</param> 
/// <exception cref="ArgumentNullException">someArgument is a null reference or Empty.</exception> 
public void SomeMethod(string someArgument) 
{ 
    ... 
} 
+4

No buscaría en Windows Forms ejemplos de las mejores prácticas más recientes en el código de Framework .NET. Pude encontrar rápidamente un ejemplo de contador en File.Copy (string, string), que arroja ArgumentNullException para null y ArgumentException para empty. – dcstraw

4

Tomando todas las cosas en cuenta que se han dicho (Joe/Ahmad Mageed), me gustaría crear una excepción para ese caso entonces.

class ArgumentNullOrEmptyException : ArgumentNullException 
+14

¿No sería mejor derivar de ArgumentException? En OOP, decir que "A o B" es una "A" no parece correcto. – dcstraw

+0

@dcstraw ArgumentNullException se deriva de ArgumentException. En este caso, creo que es mejor que ArgumentNullOrEmptyException se derive de ArgumentNullException. – Xtro

+0

También creo que su nombre debe ser StringArgumentNullOrEmptyException porque solo tiene un significado para los argumentos de cadena. – Xtro

0

Esto depende de las circunstancias realmente.

La pregunta se reduce a, ¿es realmente un error? Con eso quiero decir, ¿usted siempre espera un valor? Si lo hace, entonces probablemente su mejor apuesta aquí es la creación de su propio Exception, quizá de este modo:

class StringEmptyOrNullException : Exception 
{ 
} 

donde también podrán añadir sus propios constructores y ha añadido información, etc.

Si embargo, no es una "excepcional" en su programa, si probablemente sería una mejor idea devolver nulo el método y manejarlo desde allí.Solo recuerda, Exception's son para condiciones excepcionales.

Espero que esto ayude,

Kyle

+1

Si * haces * crea tu propia excepción, debe derivar de ArgumentException en lugar de Exception. – Joe

+0

Dependiendo del contexto realmente, en este contexto sí. Si desea usarlo en otros lugares, lo hace más genérico. Por ejemplo, si tiene un método que genera una cadena que no debería estar vacía, ArgumentException no será la mejor opción. Por lo tanto, dependiendo de la cantidad de uso que tenga y el contexto en el que se use, entonces decidirá de qué heredar. –

+0

IMO son dos situaciones diferentes: método que genera una cadena y un argumento pasado a un método, y preferiría tener dos tipos de excepciones diferentes. Es mejor ser detallado que bloquear varios tipos de situaciones de error en una sola excepción. –

0

¿Por qué no utilizar este código?

private void SomeMethod(string someArgument) 
{ 
//chek only NULL 
if(ReferenceEquals(someArgument,null)) 
    throw new ArgumentNullException("someArgument"); 

// and after trim and check 
if (someArgument.Trim() == String.Empty) 
    throw new ArgumentException("Input cannot be empty", "someArgument"); 

// do some work 
} 
Cuestiones relacionadas