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

如何通过Data Annotations实现小数范围或TBD值的多类型验证

没问题!这种混合验证场景完全可以用Data Annotations搞定,甚至不用啃复杂的正则——当然如果偏好正则也有方案,下面给你两种实用思路:

方法一:自定义验证属性(推荐,逻辑清晰易维护)

这种方式最直观,你可以完全控制验证逻辑,后续修改也方便。只需要创建一个继承自ValidationAttribute的自定义属性:

using System.ComponentModel.DataAnnotations;

public class DecimalOrTbdAttribute : ValidationAttribute
{
    private readonly decimal _minValue;
    private readonly decimal _maxValue;

    public DecimalOrTbdAttribute(decimal minValue, decimal maxValue)
    {
        _minValue = minValue;
        _maxValue = maxValue;
        ErrorMessage = $"值必须是\"TBD\"或者介于{_minValue}和{_maxValue}之间的小数(最多6位小数)";
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null)
        {
            return new ValidationResult("值不能为空");
        }

        var input = value.ToString().Trim();

        // 匹配TBD,这里是严格大小写匹配,如果需要不区分大小写,改成StringComparison.OrdinalIgnoreCase即可
        if (string.Equals(input, "TBD", StringComparison.Ordinal))
        {
            return ValidationResult.Success;
        }

        // 尝试解析为小数
        if (decimal.TryParse(input, out decimal num))
        {
            // 检查是否在(0, 99.999999)开区间内
            if (num > _minValue && num <= _maxValue)
            {
                // 检查小数位数不超过6位
                var decimalPlaces = BitConverter.GetBytes(decimal.GetBits(num)[3])[2];
                if (decimalPlaces <= 6)
                {
                    return ValidationResult.Success;
                }
                return new ValidationResult("小数位数不能超过6位");
            }
        }

        return new ValidationResult(ErrorMessage);
    }
}

使用方式

直接在你的模型属性上标注这个自定义属性就行:

public class YourModel
{
    [DecimalOrTbd(0, 99.999999)]
    public string YourValue { get; set; }
}
方法二:使用正则表达式验证

如果你想用正则一次性搞定,这里给你写好适配的表达式,并且拆解了逻辑,方便你理解:

正则表达式

^(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$

逻辑拆解

  • ^ 和 $:确保整个字符串完全匹配,避免部分匹配的情况
  • TBD:直接匹配字面量"TBD"
  • 小数部分的规则:
    • 0*[1-9]\d{0,1}(\.\d{1,6})?:匹配1-99的整数或带1-6位小数的数(比如5、99、12.345678)
    • 0\.\d{1,6}:匹配0开头的小数(比如0.123、0.999999),排除了纯0的情况,符合你(0-99.999999)的开区间需求

使用方式

在属性上标注RegularExpression属性:

public class YourModel
{
    [RegularExpression(@"^(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$", 
        ErrorMessage = "值必须是\"TBD\"或者介于0和99.999999之间的小数(最多6位小数)")]
    public string YourValue { get; set; }
}

额外说明

如果需要允许不区分大小写的"TBD"(比如"tbd"、"Tbd"),只需要在正则开头加上(?i):

^(?i)(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:05:17