c# - 枚举失败 == 当通过反射检索值时

标签 c# asp.net asp.net-mvc unobtrusive-validation

我正在尝试为 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;
}

在大多数情况下,这完全符合预期。我遇到的唯一问题是引用的属性及其值是枚举的派生词(例如,假设我们的枚举是 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 时,object == object 运算符会执行 Object.ReferenceEquals() 检查.由于枚举是值类型,它们必须被“装箱”到一个新对象中才能被转换为 objects,并且这些新对象将存在于不同的内存位置。因此,ReferenceEquals() 将为假。

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

object.Equals(value1, value2) 相对于 value1.Equals(value2) 的优势在于,如果 value1 为空。

关于c# - 枚举失败 == 当通过反射检索值时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49040065/

相关文章:

c# - 垃圾收集、.NET、C#

c# - ASP.NET MVC 中的分页和排序网格

jquery - 顶部导航栏的下拉菜单隐藏在第二个导航栏后面

c# - 在持有该方法的对象的构造函数中调用实例方法是否是一种好习惯?

css - 将 PureCSS 添加到 MVC 4.5 包

asp.net-mvc - 在 Visual Studio 2015 中创建一个空的 MVC 项目

c# - ASP.NET MVC : How do I handle a view model with many properties?

c# - 从 javascript 将参数传递给 C# 后面代码中的一个函数

asp.net - 在 web.config 文件中添加 “X-Content-Type-Options: nosniff” 后,IE 中未加载图标/图像

来自 Properties 的 C# 自定义属性