GFramework/GFramework.Core/extensions/NumericExtensions.cs
GeWuYou 475f301d9f feat(extensions): 添加多个扩展方法类和对应测试
- 新增 AsyncExtensions 提供异步任务超时、重试、安全执行等功能
- 新增 CollectionExtensions 提供集合遍历、空值检查、过滤等扩展功能
- 新增 GuardExtensions 提供参数验证的 Guard 模式扩展方法
- 新增 NumericExtensions 提供数值范围限制、插值计算等数学扩展功能
- 为所有扩展方法添加完整的单元测试覆盖正常和异常情况
- 包含详细的 XML 文档注释和使用示例代码
2026-02-25 17:28:52 +08:00

113 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace GFramework.Core.extensions;
/// <summary>
/// 数值扩展方法
/// </summary>
public static class NumericExtensions
{
/// <summary>
/// 将值限制在指定的范围内
/// </summary>
/// <typeparam name="T">实现 IComparable 的类型</typeparam>
/// <param name="value">要限制的值</param>
/// <param name="min">最小值</param>
/// <param name="max">最大值</param>
/// <returns>限制后的值</returns>
/// <exception cref="ArgumentNullException">当 value、min 或 max 为 null 时抛出</exception>
/// <exception cref="ArgumentException">当 min 大于 max 时抛出</exception>
/// <example>
/// <code>
/// var value = 150;
/// var clamped = value.Clamp(0, 100); // 返回 100
/// </code>
/// </example>
public static T Clamp<T>(this T value, T min, T max) where T : IComparable<T>
{
ArgumentNullException.ThrowIfNull(value);
ArgumentNullException.ThrowIfNull(min);
ArgumentNullException.ThrowIfNull(max);
if (min.CompareTo(max) > 0)
throw new ArgumentException($"最小值 ({min}) 不能大于最大值 ({max})");
if (value.CompareTo(min) < 0)
return min;
if (value.CompareTo(max) > 0)
return max;
return value;
}
/// <summary>
/// 检查值是否在指定范围内
/// </summary>
/// <typeparam name="T">实现 IComparable 的类型</typeparam>
/// <param name="value">要检查的值</param>
/// <param name="min">最小值</param>
/// <param name="max">最大值</param>
/// <param name="inclusive">是否包含边界值,默认为 true</param>
/// <returns>如果值在范围内则返回 true否则返回 false</returns>
/// <exception cref="ArgumentNullException">当 value、min 或 max 为 null 时抛出</exception>
/// <exception cref="ArgumentException">当 min 大于 max 时抛出</exception>
/// <example>
/// <code>
/// var value = 50;
/// var inRange = value.Between(0, 100); // 返回 true
/// var inRangeExclusive = value.Between(50, 100, inclusive: false); // 返回 false
/// </code>
/// </example>
public static bool Between<T>(this T value, T min, T max, bool inclusive = true) where T : IComparable<T>
{
ArgumentNullException.ThrowIfNull(value);
ArgumentNullException.ThrowIfNull(min);
ArgumentNullException.ThrowIfNull(max);
if (min.CompareTo(max) > 0)
throw new ArgumentException($"最小值 ({min}) 不能大于最大值 ({max})");
if (inclusive)
return value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
return value.CompareTo(min) > 0 && value.CompareTo(max) < 0;
}
/// <summary>
/// 在两个值之间进行线性插值
/// </summary>
/// <param name="from">起始值</param>
/// <param name="to">目标值</param>
/// <param name="t">插值参数0 到 1 之间)</param>
/// <returns>插值结果</returns>
/// <example>
/// <code>
/// var result = 0f.Lerp(100f, 0.5f); // 返回 50
/// </code>
/// </example>
public static float Lerp(this float from, float to, float t)
{
return from + (to - from) * t;
}
/// <summary>
/// 计算值在两个值之间的插值参数
/// </summary>
/// <param name="value">当前值</param>
/// <param name="from">起始值</param>
/// <param name="to">目标值</param>
/// <returns>插值参数(通常在 0 到 1 之间)</returns>
/// <exception cref="DivideByZeroException">当 from 等于 to 时抛出</exception>
/// <example>
/// <code>
/// var t = 50f.InverseLerp(0f, 100f); // 返回 0.5
/// </code>
/// </example>
public static float InverseLerp(this float value, float from, float to)
{
if (Math.Abs(to - from) < float.Epsilon)
throw new DivideByZeroException("起始值和目标值不能相等");
return (value - from) / (to - from);
}
}