C# 如何确定包装在对象中的值是 null 还是默认值?
C# how to determine value wrapped within object is null or default?
我目前正在编写自定义必需的验证属性,我想在值为 null 或默认值时恢复错误。对于默认值,我的意思是“”表示字符串,0 表示 int,0.0 表示双精度,null 表示对象。
为了实现这一点,我调用了以下适用于任何类型的函数
protected bool IsNullOrDefault<T>(T value)
{
return object.Equals(value, default(T));
}
测试如下:
object obj = null;
bool flag = IsNullOrDefault(obj));
flag = True
int i = 0;
bool flag = IsNullOrDefault(i);
flag = True
double d = 0.0;
Console.WriteLine(IsNullOrDefault(d));
flag = True
object value = 0;
Console.WriteLine(IsNullOrDefault(value));
flag = False
这里的对象里面又包含了int,但是它仍然认为它是一个对象,默认值为null并且当前值为 0。所以它 returns False.
问题是,我重写的框架方法将值作为对象提供给了我,所以它总是会与上面提到的最后一个场景相匹配。
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{ ....
}
根据值,我们如何将 object 转换为实际类型,在本例中为 int?因此,即使对于上面的最后一个场景,我也会收到 True。
object value = 0;
Console.WriteLine(IsNullOrDefault(value));
在这种情况下 T
是 System.Object
因此 default(T)
是 null
。
你需要检查运行时类型而不是编译时类型来处理这个:
public bool IsNullOrDefault(object value) {
if (value is Int32) {
return (Int32)value == 0;
} else if (value is Int64) {
return (Int64)value == 0L;
} else if …
} else {
return value == null;
}
}
涵盖您可能遇到的所有类型。
您必须意识到 default
和 typeof
运算符返回的值是根据 编译时 确定的,一旦您的 T
被推断为 object
,与 null
.
相比,你总是会得到你的值
最好的办法是检查 运行-time 类型:
protected bool IsNullOrDefault<T>(T value)
{
if (value == null)
return true;
var actualType = value.GetType();
if (actualType.IsValueType)
return value.Equals(Activator.CreateInstance(actualType));
return false;
}
最后我可以通过将值转换为 dynamic
类型来实现这一点,
protected bool IsNullOrDefault(object obj)
{
bool retval = false;
if (obj == null)
{
retval = true;
}
else
{
retval = IsEmpty((dynamic)obj);
}
return retval;
}
protected bool IsEmpty<T>(T value)
{
return object.Equals(value, default(T));
}
You should use dynamic
type where you want the resolution of the type to take place at run time rather than at compile time. Because of this, in this case the value self determines it's type appropriately without we telling it.
我目前正在编写自定义必需的验证属性,我想在值为 null 或默认值时恢复错误。对于默认值,我的意思是“”表示字符串,0 表示 int,0.0 表示双精度,null 表示对象。
为了实现这一点,我调用了以下适用于任何类型的函数
protected bool IsNullOrDefault<T>(T value)
{
return object.Equals(value, default(T));
}
测试如下:
object obj = null;
bool flag = IsNullOrDefault(obj));
flag = True
int i = 0;
bool flag = IsNullOrDefault(i);
flag = True
double d = 0.0;
Console.WriteLine(IsNullOrDefault(d));
flag = True
object value = 0;
Console.WriteLine(IsNullOrDefault(value));
flag = False
这里的对象里面又包含了int,但是它仍然认为它是一个对象,默认值为null并且当前值为 0。所以它 returns False.
问题是,我重写的框架方法将值作为对象提供给了我,所以它总是会与上面提到的最后一个场景相匹配。
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{ ....
}
根据值,我们如何将 object 转换为实际类型,在本例中为 int?因此,即使对于上面的最后一个场景,我也会收到 True。
object value = 0; Console.WriteLine(IsNullOrDefault(value));
在这种情况下 T
是 System.Object
因此 default(T)
是 null
。
你需要检查运行时类型而不是编译时类型来处理这个:
public bool IsNullOrDefault(object value) {
if (value is Int32) {
return (Int32)value == 0;
} else if (value is Int64) {
return (Int64)value == 0L;
} else if …
} else {
return value == null;
}
}
涵盖您可能遇到的所有类型。
您必须意识到 default
和 typeof
运算符返回的值是根据 编译时 确定的,一旦您的 T
被推断为 object
,与 null
.
最好的办法是检查 运行-time 类型:
protected bool IsNullOrDefault<T>(T value)
{
if (value == null)
return true;
var actualType = value.GetType();
if (actualType.IsValueType)
return value.Equals(Activator.CreateInstance(actualType));
return false;
}
最后我可以通过将值转换为 dynamic
类型来实现这一点,
protected bool IsNullOrDefault(object obj)
{
bool retval = false;
if (obj == null)
{
retval = true;
}
else
{
retval = IsEmpty((dynamic)obj);
}
return retval;
}
protected bool IsEmpty<T>(T value)
{
return object.Equals(value, default(T));
}
You should use
dynamic
type where you want the resolution of the type to take place at run time rather than at compile time. Because of this, in this case the value self determines it's type appropriately without we telling it.