اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
یک دقیقه
در ادامه مثال سوم قسمت قبل، در مورد حذف کدهای تکراری توسط Action و Func، در این قسمت به یک مثال نسبتا پرکاربرد دیگر آن جهت ساده سازی try/catch/finally اشاره خواهد شد.
احتمالا هزاران بار در کدهای خود چنین قطعه کدی را تکرار کردهاید:
این مورد را نیز میتوان توسط Actionها کپسوله کرد و پیاده سازی قسمت بدنه try آنرا به فراخوان واگذار نمود:
و برای نمونه جهت استفاده از آن خواهیم داشت:
یا اگر عمل انجام شده باید خروجی خاصی را بازگرداند (برخلاف یک Action که خروجی از آن انتظار نمیرود)، میتوان طراحی متد Execute را با Func انجام داد:
در این حالت فراخوانی متد Execute به نحو زیر خواهد بود:
و اگر در این بین استثنایی رخ دهد، علاوه بر ثبت جزئیات خطای رخ داده شده، نال را بازگشت خواهد داد.
از همین دست میتوان به کپسوله سازی منطق «سعی مجدد» در انجام کاری اشاره کرد:
برای مثال فرض کنید برنامه قرار است اطلاعاتی را از وب دریافت کند. ممکن است در سعی اول آن، خطای اتصال یا در دسترس نبودن لحظهای سایت رخ دهد. در اینجا نیاز خواهد بود تا این عملیات چندین بار تکرار شود؛ که نمونهای از آنرا در ذیل ملاحظه میکنید:
احتمالا هزاران بار در کدهای خود چنین قطعه کدی را تکرار کردهاید:
try { // code } catch(Exception ex) { // do something }
void Execute(Action action) { try { action(); } catch(Exception ex) { // log errors } }
Execute(() => {open a file});
یا اگر عمل انجام شده باید خروجی خاصی را بازگرداند (برخلاف یک Action که خروجی از آن انتظار نمیرود)، میتوان طراحی متد Execute را با Func انجام داد:
public static class SafeExecutor { public static T Execute<T>(Func<T> operation) { try { return operation(); } catch (Exception ex) { // Log Exception } return default(T); } }
var data = SafeExecutor.Execute<string>(() => { // do something return "result"; });
از همین دست میتوان به کپسوله سازی منطق «سعی مجدد» در انجام کاری اشاره کرد:
public static class RetryHelper { public static void RetryOperation(Action action, int numRetries, int retryTimeout) { if( action == null ) throw new ArgumentNullException("action"); do { try { action(); return; } catch { if( numRetries <= 0 ) throw; else Thread.Sleep( retryTimeout ); } } while( numRetries-- > 0 ); } }
RetryHelper.RetryOperation(() => SomeFunction(), 3, 1000);