代码之家  ›  专栏  ›  技术社区  ›  jeff17237

枚举失败==通过反射检索值时

  •  1
  • jeff17237  · 技术社区  · 8 年前

    我正在尝试为MVC 6实现一个自定义jQuery非干扰性验证属性。以下是 IsValid() 属性的实现,该属性查看类中的相邻属性并将其与编译时常量进行比较。

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        ValidationResult result = ValidationResult.Success;
    
        // Simplest case, there is something in this field
        if (!string.IsNullOrEmpty(value?.ToString()))
            return result;
    
        // Check relative field
        try
        {
            // Grab the property referenced via reflection
            var relativeProperty = validationContext.ObjectType.GetProperty(this._relativePropertyName);
    
            // Compare the runtime value of that property to the Attribute initialized value
            if (relativeProperty.GetValue(validationContext.ObjectInstance) == this._relativeValue)
            {
                // Fail if those 2 values are equal
                result = new ValidationResult(this.ErrorMessageString); 
            }
    
        }
        catch (Exception)
        {
            result = new ValidationResult(this.ErrorMessageString);
        }
    
        return result;
    }
    

    在大多数情况下,这完全符合预期。我遇到的唯一问题是,当引用的属性及其值是枚举的导数时(例如,假设我们的枚举是 Result ). 在类中实现此属性的方式如下所示:

    public class TestObject
    {
        public Result TestResult { get; set; }
        [IsEqual(nameof(TestResult), Result.Pass)]
        public string PassComment { get; set; }
    }
    

    当调试器到达该行时 if(relativeProperty.GetValue(validationContext.ObjectInstance) == this._relativeValue) 它失败了,即使 relativeProperty.GetValue(validationContext.ObjectInstance) 解析为 Result.Pass . 使用即时窗口, 相对属性。GetValue(validationContext.ObjectInstance) = 后果通过 还有 this._relativeValue = 后果通过

    小旁注,呼叫 .GetType() 两个值也相等。

    我假设这与拳击有关,但无法确定。提前谢谢。

    1 回复  |  直到 8 年前
        1
  •  5
  •   StriplingWarrior    8 年前

    不使用 == 对非强类型的事物求值相等。考虑以下因素:

    void Main()
    {
        Console.WriteLine(((object)Result.Pass) == (object)Result.Pass);
        // False
    
        Console.WriteLine(((object)Result.Pass).Equals((object)Result.Pass));
        // True
    
        Console.WriteLine(object.Equals((object)Result.Pass,(object)Result.Pass));
        // True
    }
    
    public enum Result{
        Pass, Fail
    }
    

    在C#中 == 在比较某些类型的对象时,可以重写运算符以简化语法,这样做的好处是,如果尝试 == 两种不兼容的类型。有些人认为它看起来更好。

    但是,当值向下转换为 object s、 the object == object 操作员执行 Object.ReferenceEquals() 检查由于枚举是值类型,因此它们必须“装箱”到新对象中才能转换为 objects ,这些新对象将存在于不同的内存位置。因此 ReferenceEquals() 将为false。

    相反,请使用 object.Equals() 方法,该方法传递给单个类的 .Equals() 推翻在这种情况下,枚举类型的重写 .等于() 将检查值是否可以转换为 Result ,以及结果值是否与 this 一个人的。

    优势在于 object.Equals(value1, value2) 结束 value1.Equals(value2) 如果 value1 为空。