枚举失败 == 当通过反射检索值时
Enum failing == when value retrieved via reflection
我正在尝试为 MVC 6 实现自定义 jQuery Unobtrusive Validation 属性。下面是 IsValid()
属性的实现,该属性查看 [=] 中的相邻 属性 32=] 并将其与编译时常量进行比较。
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
)。在 class:
中实现此属性类似于以下内容
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
。使用立即数 Window、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# 中,可以覆盖 ==
运算符,以便在比较某些类型的对象时简化语法,如果您尝试 ==
,这样做的好处是会提供 compile-time 错误两种不相容的类型。还有一些人认为它看起来更好。
但是,当值为 down-cast 到 object
时,object == object
运算符会执行 Object.ReferenceEquals()
检查。由于枚举是值类型,它们必须将 "boxed" 放入新对象中才能转换为 objects
,并且这些新对象将存在于不同的内存位置。因此,ReferenceEquals()
将为假。
而是使用 object.Equals()
方法,该方法传递给个人 class 的 .Equals()
覆盖。在这种情况下,枚举类型对 .Equals()
的覆盖将检查该值是否可以转换为 Result
,以及结果值是否与 this
相同。
object.Equals(value1, value2)
优于 value1.Equals(value2)
的优势在于,如果 value1
为空,则不会出现空异常。
我正在尝试为 MVC 6 实现自定义 jQuery Unobtrusive Validation 属性。下面是 IsValid()
属性的实现,该属性查看 [=] 中的相邻 属性 32=] 并将其与编译时常量进行比较。
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
)。在 class:
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
。使用立即数 Window、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# 中,可以覆盖 ==
运算符,以便在比较某些类型的对象时简化语法,如果您尝试 ==
,这样做的好处是会提供 compile-time 错误两种不相容的类型。还有一些人认为它看起来更好。
但是,当值为 down-cast 到 object
时,object == object
运算符会执行 Object.ReferenceEquals()
检查。由于枚举是值类型,它们必须将 "boxed" 放入新对象中才能转换为 objects
,并且这些新对象将存在于不同的内存位置。因此,ReferenceEquals()
将为假。
而是使用 object.Equals()
方法,该方法传递给个人 class 的 .Equals()
覆盖。在这种情况下,枚举类型对 .Equals()
的覆盖将检查该值是否可以转换为 Result
,以及结果值是否与 this
相同。
object.Equals(value1, value2)
优于 value1.Equals(value2)
的优势在于,如果 value1
为空,则不会出现空异常。