2012-06-04 17 views
7

Tengo las siguientes dos funciones, que son casi idénticas, la única diferencia es que uno usa func, el otro action. Y me gustaría combinarlos en una función si es posible.C# forma de escribir Func con retorno nulo

private static void TryCatch(Action action) 
    { 
     try 
     { 
      action(); 
     } 
     catch (Exception x) 
     { 
      Emailer.LogError(x); 
      throw; 
     } 
    } 

    private static TResult TryCatch<TResult>(Func<TResult> func) 
    { 
     try 
     { 
      return func(); 
     } 
     catch (Exception x) 
     { 
      Emailer.LogError(x); 
      throw; 
     } 
    } 

Respuesta

3

La combinación de estos dos en una función en C# realmente no es posible. El void en C# y CLR, simplemente no es un tipo y, por lo tanto, tiene una semántica de retorno diferente de una función no nula. La única forma de implementar correctamente dicho patrón es proporcionar una sobrecarga para delegados anulados y no válidos

La limitación de CLR no significa que sea imposible de hacer en todos los lenguajes de CLR. Es simplemente imposible en idiomas que usan void representar una función que no devuelve ningún valor. Este patrón es muy factible en F # porque usa Unit en lugar de void para los métodos que no devuelven un valor.

+0

Gracias por la explicación de por qué no es posible. – CaffGeek

4

Puede usar su segunda versión, Func<T>, para implementar el método Action simplemente envolviendo la Acción en una lambda. Esto elimina parte del código duplicado.

private static void TryCatch(Action action) 
{ 
    Func<object> fun => 
     { 
      action(); 
      return null; 
     }; 
    TryCatch(fun); 
} 

Dicho esto, hay una actividad general adicional implicado en hacer esto, tan personal, que probablemente dejaría la forma que tiene actualmente se implementa (sobre todo teniendo en cuenta lo breve y sencilla su versión original pasa a ser en este caso).

+0

+1 Ver mi respuesta para una sintaxis alternativa. –

+0

Gracias, como sugerí, lo dejo tal como está. Apesta No puedo reducirlo a una sola función. – CaffGeek

+0

@Chad No, podrías hacerlo de una sola línea: lo dividí en dos para que pudieras ver/entender lo que está sucediendo, pero tu método es lo suficientemente corto como para dejarlo tal como está. Sin embargo, no hay forma de eliminar la sobrecarga de métodos. –

1

Hago esto como @ReedCopsey sugiere.

Esta es la sintaxis más simple que he encontrado:

private static void TryCatch(Action action) 
{ 
    TryCatch(() => { action(); return 0; }); 
} 
+0

¿Cómo harías esto si necesitas pasar un parámetro al Func? – Nicknow

Cuestiones relacionadas