2012-09-21 31 views
8

Tengo un bucle foreach que se rompe durante el bucle en la condición del foreach mismo. ¿Hay alguna manera de try catch el elemento que lanza la excepción y luego continuar el ciclo?Excepción de captura lanzada en una condición forecech

Esto se ejecutará varias veces hasta que la excepción llegue y termine.

try { 
    foreach(b in bees) { //exception is in this line 
    string += b; 
    } 
} catch { 
    //error 
} 

Esto no funciona en absoluto, porque la excepción está en la condición de la foreach

foreach(b in bees) { //exception is in this line 
    try { 
     string += b; 
    } catch { 
    //error 
    } 
} 

Sé que algunos de ustedes van a preguntar cómo esto está sucediendo por lo que aquí es la siguiente: Excepción PrincipalOperationException se está lanzando porque un Principal (b en mi ejemplo) no se puede encontrar en GroupPrincipal (abejas).

Edit: He agregado el código a continuación. También descubrí que un miembro del grupo apuntaba a un dominio que ya no existe. Solucioné esto fácilmente al eliminar el miembro, pero mi pregunta sigue en pie. ¿Cómo manejas las excepciones que se lanzan dentro de la condición de un foreach?

PrincipalContext ctx = new PrincipalContext(ContextType.domain); 
GroupPrincipal gp1 = GroupPrincipal.FindByIdentity(ctx, "gp1"); 
GroupPrincipal gp2 = GroupPrincipal.FindByIdentity(ctx, "gp2"); 

var principals = gp1.Members.Union(gp2.Members); 

foreach(Principal principal in principals) { //error is here 
    //do stuff 
} 
+3

El problema no está en "condiciones". Está en el proceso de enumerar el objeto 'abejas'. Para fines de depuración, trate de enumerar "manualmente" las "abejas". Es una especie de 'IEnumerable ' o 'IEnumerable'. Haga manualmente '.MoveFirst()' y vea si obtiene la excepción de inmediato. –

+0

Guau, no me di cuenta de que C# no tenía un currículum el próximo ... Acabo de encontrar todos estos foros de chicos buscando el equivalente. Supongo que es simplemente otra cosa buena acerca de ser un desarrollador de VB.net. Mis disculpas compañeros – Ccorock

+0

@mellamokb, En realidad, yo tampoco lo uso demasiado. Solía ​​trabajar con un programador de C++ bastante interesante que se vio obligado a escribir en Vb.net, que arrojaría el maldito código en On resume resume next. ¿Por qué debería inventar algo aquí? – Ccorock

Respuesta

3

casi la misma que la respuesta de @Guillaume, pero "me gusta el mío mejor":

public static class Extensions 
{ 
    public static IEnumerable<T> TryForEach<T>(this IEnumerable<T> sequence, Action<Exception> handler) 
    { 
     if (sequence == null) 
     { 
      throw new ArgumentNullException("sequence"); 
     } 

     if (handler == null) 
     { 
      throw new ArgumentNullException("handler"); 
     } 

     var mover = sequence.GetEnumerator(); 
     bool more; 
     try 
     { 
      more = mover.MoveNext(); 
     } 
     catch (Exception e) 
     { 
      handler(e); 
      yield break; 
     } 

     while (more) 
     { 
      yield return mover.Current; 
      try 
      { 
       more = mover.MoveNext(); 
      } 
      catch (Exception e) 
      { 
       handler(e); 
       yield break; 
      } 
     } 
    } 
} 
+0

Me gusta más el mío también ... Sin embargo, tiene más sentido lanzar una excepción que ejecutar 'Action' si no hay enumeración. ¿Cuál es la razón para ejecutar primero 'MoveNext' en lugar de simplemente hacerlo en el ciclo? – Guillaume

+0

@Guillaume: no es un gran problema, pero de esta manera no hay retorno desde el medio del ciclo. Es un problema de estilo menor, y un poco menos para tener que pensar. –

3

Tal vez usted puede tratar de crear un método así:

public IEnumerable<T> TryForEach<T>(IEnumerable<T> list, Action executeCatch) 
    { 
     if (list == null) { executeCatch(); } 
     IEnumerator<T> enumerator = list.GetEnumerator(); 
     bool success = false; 

     do 
     { 
      try 
      { 
       success = enumerator.MoveNext(); 
      } 
      catch 
      { 
       executeCatch(); 
       success = false; 
      } 

      if (success) 
      { 
       T item = enumerator.Current; 
       yield return item; 
      } 
     } while (success); 
    } 

y se puede utilizar de esta manera:

 foreach (var bee in TryForEach(bees.GetMembers(),() => { Console.WriteLine("Error!"); })) 
     { 
     } 
+0

no bien programado: list.Count(); enumera la lista completa, y el bucle for también es la forma incorrecta de enumerar una enumeración – user287107

+0

Supongo que no funciona, porque list.Count() ya arroja el mensaje de error – user287107

+3

, además, ¿por qué debería enumerator.MoveNext(); devolver un buen valor después de lanzar una excepción? – user287107

0

Prefiero usar un controlador de excepciones agregado. sin necesidad de extensiones

.NET Framework 4,6 y 4,5

AggregateException Class no han probado el código, pero la lógica es allí.

try 
    { 
     foreach (var item in items) 
     { 
      try 
      { 
       //something 
       //your own exception (eg.) 
       if (item < 0x3) 
        throw new ArgumentException(String.Format("value is {0:x}. Elements must be greater than 0x3.")); 
      } 
      catch (Exception regularException) 
      { 
       //predefined exceptions (eg.) 
       throw new ArgumentException(regularException.InnerException.ToString()); 
      } 
     } 
    } 
    catch (AggregateException ae) 
    { 
     ae.Handle((inner) => 
     { 
      //handle your aggregate exceptions 
      Debug.WriteLine(inner.Message); 
     }); 
    } 
Cuestiones relacionadas