You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Between方法以支持多种数值类型混合及dynamic参数探讨

修复Between方法并简化实现方案

问题分析

原Between方法处理int、decimal、double及对应可空类型的混合参数时(比如Between((int)1, (decimal)1, (decimal)2)),会抛出"Cannot cast integer to decimal"异常——原因是直接用(decimal)value这类硬强制转换对不同数值类型不兼容,int无法直接强制转为decimal,需显式转换而非强制转换。同时代码存在其他小问题:DateOnly分支的null处理错误,字符串/char分支的条件重复。

修复方案(不使用dynamic)

针对数值类型,通过IConvertible接口统一转换为decimal,避免硬强制转换的问题;同时修正其他分支的错误:

static bool Between(object value, object low, object high)
{
    if (value == null && low == null && high == null)
        return false;

    // 处理数值类型(int/decimal/double及可空类型)
    if (value is IConvertible numVal || low is IConvertible numLow || high is IConvertible numHigh)
    {
        // 先处理可空类型的null值,再转换为decimal
        decimal val = numVal?.ToDecimal(null) ?? 0;
        decimal lower = numLow?.ToDecimal(null) ?? 0;
        decimal upper = numHigh?.ToDecimal(null) ?? 0;
        return val >= lower && val <= upper;
    }

    // 处理DateOnly及可空类型
    if (value is DateOnly? dateVal || low is DateOnly? dateLow || high is DateOnly? dateHigh)
    {
        DateOnly val = dateVal ?? DateOnly.MinValue;
        DateOnly lower = dateLow ?? DateOnly.MinValue;
        DateOnly upper = dateHigh ?? DateOnly.MinValue;
        return val >= lower && val <= upper;
    }

    // 处理字符串、char及可空char类型
    if (value is string || value is char? || 
        low is string || low is char? || 
        high is string || high is char?)
    {
        string valStr = value?.ToString() ?? string.Empty;
        string lowStr = low?.ToString() ?? string.Empty;
        string highStr = high?.ToString() ?? string.Empty;
        return valStr.CompareTo(lowStr) >= 0 && valStr.CompareTo(highStr) <= 0;
    }

    throw new ArgumentException("Incompatible argument types");
}

使用dynamic简化实现

在ASP.NET 8对应的最新版C#中,使用dynamic参数可以让运行时自动处理类型转换和比较逻辑,大幅简化代码:

基础版dynamic实现

static bool Between(dynamic value, dynamic low, dynamic high)
{
    if (value == null && low == null && high == null)
        return false;

    try
    {
        // 运行时自动处理类型转换和比较
        return value >= low && value <= high;
    }
    catch (InvalidOperationException)
    {
        throw new ArgumentException("Incompatible argument types");
    }
}

兼容null默认值的dynamic实现

如果需要自动将null替换为对应类型的默认值,可补充逻辑:

static bool Between(dynamic value, dynamic low, dynamic high)
{
    if (value == null && low == null && high == null)
        return false;

    // 处理null值,替换为对应类型的默认值
    dynamic val = value ?? GetDefaultValue(value?.GetType() ?? low?.GetType() ?? high.GetType());
    dynamic lower = low ?? GetDefaultValue(low?.GetType() ?? value?.GetType() ?? high.GetType());
    dynamic upper = high ?? GetDefaultValue(high?.GetType() ?? value?.GetType() ?? low.GetType());

    try
    {
        return val >= lower && val <= upper;
    }
    catch (Exception)
    {
        throw new ArgumentException("Incompatible argument types");
    }
}

private static dynamic GetDefaultValue(Type type)
{
    if (type == null) return null;
    return type.IsValueType ? Activator.CreateInstance(type) : null;
}

dynamic方案的注意事项

  • 运行时类型检查:传入无法比较的类型(比如string和int)会抛出异常,需捕获并转换为自定义ArgumentException。
  • 性能影响:dynamic会带来轻微的运行时开销,但多数业务场景下可忽略。
  • 可空类型支持:基础版不自动处理null与数值的比较,需额外逻辑补充默认值替换。

关键修正点

  1. 数值类型:用IConvertible.ToDecimal替代硬强制转换,支持所有数值类型及可空类型的转换。
  2. DateOnly分支:修正value ?? 0的错误,改为DateOnly.MinValue。
  3. 字符串/char分支:简化类型判断,用ToString()统一处理char和string类型。
  4. dynamic方案:利用C#动态类型特性,自动处理类型转换和比较,减少冗余代码。

内容的提问来源于stack exchange,提问作者Andrus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:18:13