using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace DragonSoul; public sealed class NotEqualsException : Exception { public NotEqualsException(string v1,string v2): base($"{v1} != {v2}") { } } public sealed class EqualsException : Exception { public EqualsException(string v1,string v2): base($"{v1} == {v2}") { } } public static class Verify { public static void IsNotNull([NotNull]this T? t) { if (t == null) { throw new NullReferenceException($"{typeof(T)}"); } } public static void IsNotNullWithMessage([NotNull]this T? t,[CallerArgumentExpression(nameof(t))]string? message=null) { if (t == null) { throw new NullReferenceException(message); } } [Conditional("DEBUG")] public static void Argument(bool condition, string message, [CallerArgumentExpression("condition")] string? conditionExpression = null) { if (!condition) throw new ArgumentException(message: message, paramName: conditionExpression); } [Conditional("DEBUG")] public static void InRange(int argument, int low, int high, [CallerArgumentExpression("argument")] string? argumentExpression = null, [CallerArgumentExpression("low")] string? lowExpression = null, [CallerArgumentExpression("high")] string? highExpression = null) { if (argument < low) { throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $"{argumentExpression} ({argument}) cannot be less than {lowExpression} ({low})."); } if (argument > high) { throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $"{argumentExpression} ({argument}) cannot be greater than {highExpression} ({high})."); } } [Conditional("DEBUG")] public static void ShouldBe(this T? @this, T? expected, [CallerArgumentExpression("this")] string? thisExpression = null, [CallerArgumentExpression("expected")] string? expectedExpression = null ) { if (@this == null) { if(expected==null) return; } else if(@this.Equals(expected)) return; throw new NotEqualsException(thisExpression??string.Empty, expectedExpression??string.Empty); } [Conditional("DEBUG")] public static void ShouldNotBe(this T? @this, T? expected, [CallerArgumentExpression("this")] string? thisExpression = null, [CallerArgumentExpression("expected")] string? expectedExpression = null) { if (@this == null) { if(expected!=null) return; } else if(!@this.Equals(expected)) return; throw new EqualsException(thisExpression??string.Empty, expectedExpression??string.Empty); } public static T Single(this IList? array) { array.IsNotNull(); Verify.Argument(array.Count == 1, "Array must contain a single element."); return array[0]; } public static T ElementAt(this IList? array, int index) { array.IsNotNull(); Verify.InRange(index, 0, array.Count - 1); return array[index]; } public static void Dispose(ref T? obj) { if (obj == null) { return; } if (obj is IDisposable disposable) { disposable.Dispose(); } obj = default; } }