diff --git a/src/CuteUtils.Tests/Misc/SafeRetryTests.cs b/src/CuteUtils.Tests/Misc/SafeRetryTests.cs deleted file mode 100644 index dcc597c..0000000 --- a/src/CuteUtils.Tests/Misc/SafeRetryTests.cs +++ /dev/null @@ -1,222 +0,0 @@ -using CuteUtils.Misc; - -namespace CuteUtils.Tests.Misc; - -[TestClass] -public class SafeRetryTests -{ - [TestMethod] - public async Task RetryAsyncT_SucceedsFirstTry() - { - int callCount = 0; - int result = await SafeRetry.RetryAsync(async () => - { - callCount++; - await Task.Delay(10); - return 42; - }); - Assert.AreEqual(1, callCount); - Assert.AreEqual(42, result); - } - - [TestMethod] - public async Task RetryAsyncT_RetriesAndSucceeds() - { - int callCount = 0; - int result = await SafeRetry.RetryAsync(async () => - { - callCount++; - if (callCount < 3) - { - throw new InvalidOperationException(); - } - - await Task.Delay(10); - return 99; - }, maxRetries: 5, delay: TimeSpan.FromMilliseconds(1)); - Assert.AreEqual(3, callCount); - Assert.AreEqual(99, result); - } - - [TestMethod] - public async Task RetryAsyncT_ThrowsAfterMaxRetries() - { - int callCount = 0; - _ = await Assert.ThrowsExceptionAsync(async () => - { - _ = await SafeRetry.RetryAsync(() => - { - callCount++; - throw new InvalidOperationException("fail"); - }, maxRetries: 2, delay: TimeSpan.FromMilliseconds(1)); - }); - Assert.AreEqual(2, callCount); - } - - [TestMethod] - public async Task RetryAsync_SucceedsFirstTry() - { - int callCount = 0; - await SafeRetry.RetryAsync(async () => - { - callCount++; - await Task.Delay(10); - }); - Assert.AreEqual(1, callCount); - } - - [TestMethod] - public async Task RetryAsync_RetriesAndSucceeds() - { - int callCount = 0; - await SafeRetry.RetryAsync(async () => - { - callCount++; - if (callCount < 2) - { - throw new Exception(); - } - - await Task.Delay(10); - }, maxRetries: 3, delay: TimeSpan.FromMilliseconds(1)); - Assert.AreEqual(2, callCount); - } - - [TestMethod] - public async Task RetryAsync_ThrowsAfterMaxRetries() - { - int callCount = 0; - _ = await Assert.ThrowsExceptionAsync(async () => - { - await SafeRetry.RetryAsync(() => - { - callCount++; - throw new Exception(); - }, maxRetries: 2, delay: TimeSpan.FromMilliseconds(1)); - }); - Assert.AreEqual(2, callCount); - } - - [TestMethod] - public void RetryT_SucceedsFirstTry() - { - int callCount = 0; - int result = SafeRetry.Retry(() => - { - callCount++; - return 7; - }); - Assert.AreEqual(1, callCount); - Assert.AreEqual(7, result); - } - - [TestMethod] - public void RetryT_RetriesAndSucceeds() - { - int callCount = 0; - int result = SafeRetry.Retry(() => - { - callCount++; - if (callCount < 4) - { - throw new Exception(); - } - - return 123; - }, maxRetries: 5, delay: TimeSpan.FromMilliseconds(1)); - Assert.AreEqual(4, callCount); - Assert.AreEqual(123, result); - } - - [TestMethod] - public void RetryT_ThrowsAfterMaxRetries() - { - int callCount = 0; - _ = Assert.ThrowsException(() => - { - _ = SafeRetry.Retry(() => - { - callCount++; - throw new Exception(); - }, maxRetries: 3, delay: TimeSpan.FromMilliseconds(1)); - }); - Assert.AreEqual(3, callCount); - } - - [TestMethod] - public void Retry_SucceedsFirstTry() - { - int callCount = 0; - SafeRetry.Retry(() => - { - callCount++; - }); - Assert.AreEqual(1, callCount); - } - - [TestMethod] - public void Retry_RetriesAndSucceeds() - { - int callCount = 0; - SafeRetry.Retry(() => - { - callCount++; - if (callCount < 2) - { - throw new Exception(); - } - }, maxRetries: 3, delay: TimeSpan.FromMilliseconds(1)); - Assert.AreEqual(2, callCount); - } - - [TestMethod] - public void Retry_ThrowsAfterMaxRetries() - { - int callCount = 0; - _ = Assert.ThrowsException(() => - { - SafeRetry.Retry(() => - { - callCount++; - throw new Exception(); - }, maxRetries: 2, delay: TimeSpan.FromMilliseconds(1)); - }); - Assert.AreEqual(2, callCount); - } - - [TestMethod] - public async Task RetryAsyncT_ThrowsArgumentNullException() - { - _ = await Assert.ThrowsExceptionAsync(async () => - { - _ = await SafeRetry.RetryAsync(null!); - }); - } - - [TestMethod] - public async Task RetryAsync_ThrowsArgumentNullException() - { - _ = await Assert.ThrowsExceptionAsync(async () => - { - await SafeRetry.RetryAsync(null!); - }); - } - - [TestMethod] - public void RetryT_ThrowsArgumentNullException() - { - _ = Assert.ThrowsException(() => - { - _ = SafeRetry.Retry(null!); - }); - } - - [TestMethod] - public void Retry_ThrowsArgumentNullException() - { - _ = Assert.ThrowsException(() => - { - SafeRetry.Retry(null!); - }); - } -} \ No newline at end of file diff --git a/src/CuteUtils/Misc/SafeRetry.cs b/src/CuteUtils/Misc/Try.cs similarity index 51% rename from src/CuteUtils/Misc/SafeRetry.cs rename to src/CuteUtils/Misc/Try.cs index d99fd3a..bd41ed6 100644 --- a/src/CuteUtils/Misc/SafeRetry.cs +++ b/src/CuteUtils/Misc/Try.cs @@ -1,9 +1,11 @@ -namespace CuteUtils.Misc; +using System.Diagnostics; + +namespace CuteUtils.Misc; /// /// Provides methods for safely retrying actions and functions with optional delay and retry count. /// -public static class SafeRetry +public static class Try { /// /// Retries an asynchronous function returning a value, up to a specified number of times, with an optional delay between attempts. @@ -127,4 +129,155 @@ public static class SafeRetry } throw new InvalidOperationException($"Failed after {maxRetries} attempts.", lastException); } + + /// + /// Executes a synchronous action and catches any exception, writing it to the debug output. + /// + /// The action to execute. + public static void Catch(Action action) + { + try + { + action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + /// + /// Executes a synchronous action and catches any exception, writing it to the debug output and returning it via an out parameter. + /// + /// The action to execute. + /// When this method returns, contains the exception that was thrown, or null if no exception was thrown. + public static void Catch(Action action, out Exception? exception) + { + exception = null; + try + { + action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + exception = ex; + } + } + + /// + /// Executes a synchronous function and catches any exception, writing it to the debug output. Returns the default value if an exception occurs. + /// + /// The return type of the function. + /// The function to execute. + /// The result of the function, or the default value of if an exception occurs. + public static T? Catch(Func action) + { + try + { + return action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return default; + } + } + + /// + /// Executes a synchronous function and catches any exception, writing it to the debug output and returning the exception via an out parameter. + /// Returns the default value if an exception occurs. + /// + /// The return type of the function. + /// The function to execute. + /// When this method returns, contains the exception that was thrown, or null if no exception was thrown. + /// The result of the function, or the default value of if an exception occurs. + public static T? Catch(Func action, out Exception? exception) + { + exception = null; + try + { + return action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + exception = ex; + return default; + } + } + + /// + /// Executes an asynchronous action and catches any exception, writing it to the debug output. + /// + /// The asynchronous action to execute. + /// A task that represents the asynchronous operation. + public static async Task CatchAsync(Func action) + { + try + { + await action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + /// + /// Executes an asynchronous function and catches any exception, writing it to the debug output. + /// Returns the default value if an exception occurs. + /// + /// The return type of the function. + /// The asynchronous function to execute. + /// The result of the function, or the default value of if an exception occurs. + public static async Task CatchAsync(Func> action) + { + try + { + return await action(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return default; + } + } + + /// + /// Waits for an asynchronous task to complete and catches any exception, writing it to the debug output. + /// + /// The task to await. + /// A task that represents the asynchronous operation. + public static async Task CatchAsync(Task task) + { + try + { + await task; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } + + /// + /// Waits for an asynchronous task that returns a result and catches any exception, writing it to the debug output. + /// Returns the default value if an exception occurs. + /// + /// The return type of the task. + /// The task to await. + /// The result of the task, or the default value of if an exception occurs. + public static async Task CatchAsync(Task task) + { + try + { + return await task; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return default; + } + } } \ No newline at end of file