C#确定DateTime和DateTime之间的区别? (可空)

时间:2016-01-26 16:20:18

标签: c# reflection

我正在尝试确定DateTime和DateTime之间的区别?使用反射。请参阅下面的测试代码:

    public class TestClass
    {
        public DateTime testDate1 { get; set; }
        public DateTime? testDate2 { get; set; }
    }

    public void Test()
    {
        TestClass testing = new TestClass();
        var props = typeof(TestClass).GetProperties();
        foreach (PropertyInfo p in props)
        {
            object o = p.GetValue(testing);
            if (typeof(DateTime?).IsInstanceOfType(o))
            {
                o = DateTime.Now;
            }
            if (typeof(DateTime).IsInstanceOfType(o))
            {
                if (((DateTime)o) == DateTime.MinValue)
                {
                    o = null;
                }
            }
            Console.WriteLine(string.Format("{0} = {1}", p.Name, (o ?? "NULL").ToString()));
        }

    }

此代码的输出与我期望的相反。目前的输出是:

testDate1 = 26/01/2016 16:15:00

testDate2 = NULL

我期望testDate1为null,testDate2为包含值。

调试此代码时,似乎第一次使用testDate1传递了两个typeof if语句,第二次传递失败了两个if语句。任何人都可以帮助我理解并希望尝试捕获日期时间的特定可空实例吗?

要注意我还试过切换到Nullable的定义和测试,以防万一,但没有区别。

非常感谢!

3 个答案:

答案 0 :(得分:2)

答案是你不能。

如果你有一个object date,则无法知道它是否来自nullabe DateTime

DateTime? nullable = DateTime.Now;
object o = nullable;

o的分配在道德上等同于

object temp = null;

if (nullable.HasValue)
{
    temp = nullable.Value;
}

o = temp;

正如您所看到的,可空类型的信息丢失了,您真正得到的是盒装可空的值。

通过简单地执行o.GetType()即可轻松查看,如果可以为空,则会返回DateTime,如果没有,则会返回NullReferenceException

这并不意味着您无法确定属性,方法或成员的声明类型是否可为空。你可以通过反思轻松地做到这一点。

答案 1 :(得分:2)

首先,请注意testDate1永远不能为空,因为DateTime结构。如果您声明DateTime而未对其进行初始化,则会获得默认值DateTime.MinValue。另一方面,testDate2是一个Nullable结构,其默认值为null(-ish ...它实际上是一个表示null的值,但不是null本身)。

IsInstanceOfType在后台使用o的{​​{1}}方法来验证其类型与您要比较的类型(在本例中为GetType())相同。但是,如果您查看documentation,请说明:

  

在Nullable类型上调用GetType会导致在将类型隐式转换为Object时执行装箱操作。因此,GetType始终返回表示基础类型的Type对象,而不是Nullable类型。

因此,如果您逐步执行DateTime?属性的foreach循环,您将看到第一个条件将返回true(因为testDate1不能为null,这意味着它必须属于testDate1类型。然后,您进入第二个if条件(虽然这实际上只是再次进行相同的检查),但是如果因为DateTime当前具有值o,则不会进入内部。

现在单步执行DateTime.Now(保存空值),您将看到不输入if-conditionals的 ,因为null没有类型。因此,在循环的第二次迭代中,您的对象将保持为null,从而为您提供在那里看到的输出。

注意:您知道,您向testDate2“分配”值的方式根本不会修改原始的TestClass。请考虑以下事项:

o

答案 2 :(得分:0)

感谢您提供了许多有用的评论和链接。我意识到这是我应该检查的属性,而不是对象。我正在使用这个:

Nullable.GetUnderlyingType(p.PropertyType)

它允许我确定我正在处理的内容并且非常有效。我仍然最终打开typeof(T).Name但是当我来到它时我将穿过那座桥:)

我必须忍受功能代码与丑陋代码仍然是一场内战的事实!