SafeMath.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
  2. //
  3. // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
  4. //
  5. // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
  6. using System.Globalization;
  7. namespace Admin.NET.Core;
  8. using System;
  9. /// <summary>
  10. /// 安全的基本数学运算方法类
  11. /// </summary>
  12. public static class SafeMath
  13. {
  14. /// <summary>
  15. /// 安全加法
  16. /// </summary>
  17. public static T Add<T>(object left, object right, int precision = 2, T defaultValue = default, bool throwOnError = false) where T : struct, IComparable, IConvertible, IFormattable
  18. {
  19. return PerformOperation(left, right, (a, b) => a + b, precision, defaultValue, throwOnError);
  20. }
  21. /// <summary>
  22. /// 安全减法
  23. /// </summary>
  24. public static T Sub<T>(object left, object right, int precision = 2, T defaultValue = default, bool throwOnError = false) where T : struct, IComparable, IConvertible, IFormattable
  25. {
  26. return PerformOperation(left, right, (a, b) => a - b, precision, defaultValue, throwOnError);
  27. }
  28. /// <summary>
  29. /// 安全乘法
  30. /// </summary>
  31. public static T Mult<T>(object left, object right, int precision = 2, T defaultValue = default, bool throwOnError = false) where T : struct, IComparable, IConvertible, IFormattable
  32. {
  33. return PerformOperation(left, right, (a, b) => a * b, precision, defaultValue, throwOnError);
  34. }
  35. /// <summary>
  36. /// 安全除法
  37. /// </summary>
  38. public static T Div<T>(object left, object right, int precision = 2, T defaultValue = default, bool throwOnDivideByZero = false) where T : struct, IComparable, IConvertible, IFormattable
  39. {
  40. return PerformOperation(left, right, (a, b) =>
  41. {
  42. if (b != 0) return a / b;
  43. if (throwOnDivideByZero) throw new DivideByZeroException("除数不能为0");
  44. return SafeConvert<decimal>(defaultValue);
  45. }, precision, defaultValue, throwOnDivideByZero);
  46. }
  47. /// <summary>
  48. /// 安全类型转换
  49. /// </summary>
  50. public static T SafeConvert<T>(object value, T defaultValue = default) where T : struct, IComparable, IConvertible, IFormattable
  51. {
  52. if (value == null) return defaultValue;
  53. try
  54. {
  55. return (T)Convert.ChangeType(value, typeof(T));
  56. }
  57. catch
  58. {
  59. return defaultValue;
  60. }
  61. }
  62. /// <summary>
  63. /// 执行数学运算
  64. /// </summary>
  65. private static T PerformOperation<T>(object left, object right, Func<decimal, decimal, decimal> operation, int precision, T defaultValue, bool throwOnError) where T : struct, IComparable, IConvertible, IFormattable
  66. {
  67. try
  68. {
  69. decimal leftValue = ConvertToDecimal(left);
  70. decimal rightValue = ConvertToDecimal(right);
  71. decimal result = operation(leftValue, rightValue);
  72. return SafeConvert(Math.Round(result, precision, MidpointRounding.AwayFromZero), defaultValue);
  73. }
  74. catch
  75. {
  76. if (throwOnError) throw;
  77. return defaultValue;
  78. }
  79. }
  80. /// <summary>
  81. /// 将输入值转换为 decimal
  82. /// </summary>
  83. public static decimal ConvertToDecimal(object value)
  84. {
  85. return value switch
  86. {
  87. null => 0m,
  88. int intValue => intValue,
  89. float floatValue => (decimal)floatValue,
  90. double doubleValue => (decimal)doubleValue,
  91. decimal decimalValue => decimalValue,
  92. long longValue => longValue,
  93. short shortValue => shortValue,
  94. byte byteValue => byteValue,
  95. string stringValue when decimal.TryParse(stringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal parsedValue) => parsedValue, // 尝试解析字符串
  96. _ => throw new InvalidCastException($"不支持的类型: {value.GetType().Name}")
  97. };
  98. }
  99. }