2012-06-04 14 views
7

Mam dwie następujące funkcje, które są prawie identyczne, jedyną różnicą jest to, że jeden używa func, drugi action. I chciałbym połączyć je w jedną funkcję, jeśli to możliwe.C# sposób pisania Func z pustym powrotem

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; 
     } 
    } 

Odpowiedz

3

Łączenie tych dwóch w jedną funkcję w języku C# naprawdę nie jest możliwe. void w C# i CLR, po prostu nie jest typem, a zatem ma inną semantykę powrotu niż funkcja non-void. Jedynym sposobem prawidłowego wdrożenia takiego szablonu jest zapewnienie przeciążenia dla nieotwartych i nieusuwalnych delegatów. Ograniczenie CLR nie oznacza, że ​​nie można tego zrobić w każdym języku CLR. W językach, które używają void, jest niemożliwe, aby reprezentować funkcję, która nie zwraca żadnych wartości. Ten wzorzec jest bardzo wykonalny w języku F #, ponieważ używa Unit zamiast void dla metod, które nie zwracają wartości.

+0

Dzięki za wyjaśnienie, dlaczego nie jest to możliwe. – CaffGeek

4

Możesz użyć drugiej, Func<T> wersji, aby zaimplementować metodę Action, po prostu zawijając akcję w lambda. Eliminuje to część zduplikowanego kodu.

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

Mając na uwadze powyższe, istnieje dodatkowy narzut zaangażowany w ten sposób, tak osobiście, to bym chyba zostawić to tak, jak w obecnie wdrażany (szczególnie biorąc pod uwagę jak krótka i prosta oryginalna wersja dzieje się w ta sprawa).

+0

+1 Zobacz moją odpowiedź dla alternatywnej składni. –

+0

Dzięki, jak zasugerowałem, zostawię to, jak jest. Do bani nie mogę tak naprawdę zredukować go do jednej funkcji. – CaffGeek

+0

@Chad No - możesz zrobić z niego jedną linijkę - podzielę ją na dwie części, abyś mógł zobaczyć/zrozumieć, co się dzieje, ale twoja metoda jest wystarczająco krótka, że ​​zostawiłbym ją tak, jak jest. Nie można jednak wyeliminować przeciążenia metody. –

1

Robię to jak sugeruje @ReedCopsey.

Jest to najprostszy składnia znalazłem:

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

Jak by to zrobić, jeśli musisz przekazać parametr do Func? – Nicknow