繁体   English   中英

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

[英]Enum failing == when value retrieved via reflection

我正在尝试为MVC 6实现自定义jQuery Unobtrusive Validation属性。下面是该属性的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;
}

在大多数情况下,这完全符合预期。 我唯一遇到的问题是当引用的属性及其值是Enum的派生类时(例如,让我们假设枚举为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 ,它也会失败。 使用立即窗口, relativeProperty.GetValue(validationContext.ObjectInstance) = Result.Pass以及this._relativeValue = Result.Pass

小注释,在两个值上调用.GetType()也相等。

我假设这与拳击有关,但无法查明。 提前致谢。

不要使用==来评估非强类型输入的相等性。 考虑以下:

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时, object == object操作符将执行Object.ReferenceEquals()检查。 由于枚举是值类型,因此必须将它们“装箱”到新对象中才能转换为objects ,并且这些新对象将存在于不同的内存位置。 因此, ReferenceEquals()将为false。

而是使用object.Equals()方法,该方法传递给各个类的.Equals()覆盖。 在这种情况下,Enum类型对.Equals()的覆盖将检查该值是否可以转换为Result ,以及结果值是否与this值相同。

value1.Equals(value2) object.Equals(value1, value2)value1.Equals(value2) object.Equals(value1, value2)的优势在于object.Equals(value1, value2)如果value1为null,则不会获得null异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM