我如何检查一个给定的对象是否为空,换句话说,如何实现以下方法…
bool IsNullableValueType(object o)
{
...
}
我正在寻找可空值类型。我没有想到引用类型。
//Note: This is just a sample. The code has been simplified
//to fit in a post.
public class BoolContainer
{
bool? myBool = true;
}
var bc = new BoolContainer();
const BindingFlags bindingFlags = BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance
;
object obj;
object o = (object)bc;
foreach (var fieldInfo in o.GetType().GetFields(bindingFlags))
{
obj = (object)fieldInfo.GetValue(o);
}
obj现在指向bool类型(System.Boolean)的值为true的对象。我真正想要的是一个Nullable<bool>类型的对象
所以现在我决定检查o是否为空,并在obj周围创建一个可空的包装器。
也许有点偏离主题,但仍然是一些有趣的信息。我发现很多人使用nullable. getunderlyingtype () != null来标识类型是否为空。这显然是可行的,但微软建议以下类型。IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)(参见http://msdn.microsoft.com/en-us/library/ms366789.aspx)。
我是从性能的角度来看待这个问题的。下面的测试(一百万次尝试)的结论是,当类型为空时,Microsoft选项提供了最佳性能。
nulable . getunderlyingtype (): 1335ms(慢3倍)
GetGenericTypeDefinition() == typeof(Nullable<>): 500ms
我知道我们谈论的是一小段时间,但每个人都喜欢调整毫秒:-)!所以如果你的老板想让你减少几毫秒,那么这个就是你的救星……
/// <summary>Method for testing the performance of several options to determine if a type is nullable</summary>
[TestMethod]
public void IdentityNullablePerformanceTest()
{
int attempts = 1000000;
Type nullableType = typeof(Nullable<int>);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
{
Assert.IsTrue(Nullable.GetUnderlyingType(nullableType) != null, "Expected to be a nullable");
}
Console.WriteLine("Nullable.GetUnderlyingType(): {0} ms", stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
{
Assert.IsTrue(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>), "Expected to be a nullable");
}
Console.WriteLine("GetGenericTypeDefinition() == typeof(Nullable<>): {0} ms", stopwatch.ElapsedMilliseconds);
stopwatch.Stop();
}
有一个使用方法重载的非常简单的解决方案
http://deanchalk.com/is-it-nullable/
摘录:
public static class ValueTypeHelper
{
public static bool IsNullable<T>(T t) { return false; }
public static bool IsNullable<T>(T? t) where T : struct { return true; }
}
then
static void Main(string[] args)
{
int a = 123;
int? b = null;
object c = new object();
object d = null;
int? e = 456;
var f = (int?)789;
bool result1 = ValueTypeHelper.IsNullable(a); // false
bool result2 = ValueTypeHelper.IsNullable(b); // true
bool result3 = ValueTypeHelper.IsNullable(c); // false
bool result4 = ValueTypeHelper.IsNullable(d); // false
bool result5 = ValueTypeHelper.IsNullable(e); // true
bool result6 = ValueTypeHelper.IsNullable(f); // true
也许有点偏离主题,但仍然是一些有趣的信息。我发现很多人使用nullable. getunderlyingtype () != null来标识类型是否为空。这显然是可行的,但微软建议以下类型。IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)(参见http://msdn.microsoft.com/en-us/library/ms366789.aspx)。
我是从性能的角度来看待这个问题的。下面的测试(一百万次尝试)的结论是,当类型为空时,Microsoft选项提供了最佳性能。
nulable . getunderlyingtype (): 1335ms(慢3倍)
GetGenericTypeDefinition() == typeof(Nullable<>): 500ms
我知道我们谈论的是一小段时间,但每个人都喜欢调整毫秒:-)!所以如果你的老板想让你减少几毫秒,那么这个就是你的救星……
/// <summary>Method for testing the performance of several options to determine if a type is nullable</summary>
[TestMethod]
public void IdentityNullablePerformanceTest()
{
int attempts = 1000000;
Type nullableType = typeof(Nullable<int>);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
{
Assert.IsTrue(Nullable.GetUnderlyingType(nullableType) != null, "Expected to be a nullable");
}
Console.WriteLine("Nullable.GetUnderlyingType(): {0} ms", stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
for (int attemptIndex = 0; attemptIndex < attempts; attemptIndex++)
{
Assert.IsTrue(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>), "Expected to be a nullable");
}
Console.WriteLine("GetGenericTypeDefinition() == typeof(Nullable<>): {0} ms", stopwatch.ElapsedMilliseconds);
stopwatch.Stop();
}