Sono venuto con una piccola estensione quando voglio rapidamente a try/catch ad ogni iterazione di un IEnumerable<T>
Uso
public void Test()
{
List<string> completedProcesses = initialEnumerable
.SelectTry(x => RiskyOperation(x))
.OnCaughtException(exception => { _logger.Error(exception); return null; })
.Where(x => x != null) // filter the ones which failed
.ToList();
}
L'estensione
public static class OnCaughtExceptionExtension
{
public static IEnumerable<SelectTryResult<TSource, TResult>> SelectTry<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> selector)
{
foreach (TSource element in enumerable)
{
SelectTryResult<TSource, TResult> returnedValue;
try
{
returnedValue = new SelectTryResult<TSource, TResult>(element, selector(element), null);
}
catch (Exception ex)
{
returnedValue = new SelectTryResult<TSource, TResult>(element, default(TResult), ex);
}
yield return returnedValue;
}
}
public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<Exception, TResult> exceptionHandler)
{
return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException));
}
public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<TSource, Exception, TResult> exceptionHandler)
{
return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException));
}
public class SelectTryResult<TSource,TResult>
{
internal SelectTryResult(TSource source, TResult result, Exception exception)
{
Source = source;
Result = result;
CaughtException = exception;
}
public TSource Source { get; private set; }
public TResult Result { get; private set; }
public Exception CaughtException { get; private set; }
}
}
Potremmo eventualmente andare un po 'più avendo un'estensione SkipOnException
, accettando facoltativamente un gestore di eccezioni per esempio.
Che cosa consideri un abuso di eccezione? Nella mia logica aziendale, ho un metodo per calcolare la retribuzione di un dipendente. Ci sono varie cose che possono andare storte, come il dipendente che non ha un salario. Ho fatto un'eccezione personalizzata che posso lanciare e prendere nel mio controller e inserire il mio modello di visualizzazione. Questo è male? – Pluc
@Pluc: il dipendente * intende * avere un salario? Se è così, mancare sembra eccezionale. Se è in qualche modo previsto, probabilmente non utilizzerei eccezioni per gestirlo. –