2011-04-04 10 views
9

he el siguiente escenario:forma elegante de manejar elemento no se encuentra en una colección en C#

  1. Tengo un bucle foreach que se repite a través de una colección, si se encuentra un artículo (en base a criterios como en el ejemplo a continuación), devolverá ese artículo.

Si no, ¿cuál es la forma más elegante para hacer frente a esta excepción. Tengo una nueva idea de arrojar nueva, pero creo que hay una manera más elegante.

Código es:

foreach (SPContentType type in sPContentTypeCollection) 
      { 
       if (type.Name == contentTypeName) 
       { 
        return type; 
       } 
      } 

throw new NotImplementedException(); 

Como se puede ver, no es lo que yo llamaría un código legible. ¿Cómo puedo hacer que sea más fácil para el siguiente hombre mantener? En una nota lateral, hace lo que debería desde una perspectiva técnica.

Respuesta

10

Bueno NotImplementedException es ciertamente apropiado, porque tiene implementado el método ... pero ¿qué clase de excepción debe tirar? Realmente, depende del contexto, para ser honesto.

A veces sería apropiado devolver nulo para indicar un valor faltante. Otras veces, lanzar una excepción está bien, posiblemente un InvalidOperationException por ejemplo. Debe lanzar una excepción si esta situación representa un error de alguna descripción, en lugar de que sea una situación perfectamente razonable que la persona que llama debe esperar que ocurra.

En cuanto al resto del código ... si está utilizando .NET 3.5 es posible que utilices LINQ:

return sPContentTypeCollection.Cast<SPContentType>() 
           .First(type => type.Name == contentTypeName); 

Eso generará un InvalidOperationException de forma automática si no se encuentra el nombre . O si desea devolver nulo:

// type shortened to t to avoid scrollbars... 
return sPContentTypeCollection.Cast<SPContentType>() 
           .FirstOrDefault(t => t.Name == contentTypeName); 
+0

supongo, no me pide la pregunta correctamente. Lo que me preocupa es el lanzamiento "colgado" directamente después de la parte de trabajo hecho. Casi se siente mal tener un lanzamiento allí (independientemente del tipo de excepción). Si el código llegó a este punto ... algo debe estar mal. ¿Es esto aceptable, o sería una mala práctica? –

+0

@JL: Perfectamente aceptable, en mi opinión. Más agradable para usar LINQ en primer lugar cuando sea posible, por supuesto. Si crees que no es obvio por qué está ahí, siempre puedes usar un comentario, pero espero que la documentación del método lo aclare. –

+0

Soy un fan de dejar que la persona que llama decida qué significan realmente los resultados. Si esto es algo muy malo el 100% del tiempo, adelante y lanza una excepción. De lo contrario, deje que la persona que llama decida si un resultado nulo garantiza el lanzamiento o no. ¿Qué tan fatal es si no puede encontrar su tipo? Si es una elección entre try..catch o null handling, tomaré un manejo nulo. Sin embargo, si necesita generar una excepción para el manejo externo, entonces sus manos están atadas ... –

3

NotImplementedException es definitivamente la excepción incorrecta. Prefiero lanzar una excepción personalizada como, por ejemplo, ElementNotFoundInCollection.

Otro enfoque sería simplemente devolver nulo. Luego debe verificar el lado de la llamada si el objeto devuelto no es nulo.

3

Realmente depende de si este es un caso esperado o excepcional.

Si el artículo se compara con se pasa a un método y realmente siempre debe ser un elemento coincidente en la colección que había una excepción ArgumentOutOfRangeException.

Si se espera que a veces no se encuentre un artículo que coincida, simplemente devolvería null para indicar que el artículo solicitado no se encontró.

2

Estoy de acuerdo con Rofl en que NotImplemented está mal. Si no quiere definir su propia clase de excepción, KeyNotFoundException está bastante cerca.

De vuelta null también es una opción.

2

Bueno, podría valer la pena analizar cómo el propio .NET Framework maneja este caso en sus propias clases. Por ejemplo, tome Dictionary<TKey, TValue>.Hay dos maneras de obtener un valor de un diccionario:

  1. myDic[key]

    • Ventaja: corta; pueden ser asignados a (y por lo tanto puede utilizar ++ y operadores similares)
    • Desventaja: lanza KeyNotFoundException si la clave no existe
  2. myDic.TryGetValue(key, out value)

    • Ventaja: no tira (pero devuelve false) si no se encuentra la clave
    • Desventaja: solo se puede obtener el valor, no se establece

Si solo necesita obtenga un valor, y no desea lanzar una excepción, entonces el segundo es claramente preferible.

Por lo tanto, en su caso, escriba la función parecida:

public bool TryGetType(string contentTypeName, out SPContentType result) 
{ 
    foreach (SPContentType type in sPContentTypeCollection) 
    { 
     if (type.Name == contentTypeName) 
     { 
      result = type; 
      return true; 
     } 
    } 
    result = default(SPContentType); 
    return false; 
} 
Cuestiones relacionadas