简体   繁体   English

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

[英]C# Determine difference between DateTime and DateTime? (Nullable)

I am trying to determine the difference between a DateTime and a DateTime? 我试图确定DateTime和DateTime之间的区别? using reflection. 使用反射。 Please see my test code below: 请在下面查看我的测试代码:

    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()));
        }

    }

The output of this code is the opposite to what i would expect. 此代码的输出与我期望的相反。 Currently the output is: 当前输出为:

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

testDate2 = NULL testDate2 = NULL

I am expecting testDate1 to be null and testDate2 to contain the value. 我期望testDate1为null,而testDate2包含该值。

When debugging this code, it seems that the first pass using testDate1 passes both of the typeof if statements, the second fails both of the if statements. 在调试此代码时,似乎第一次使用testDate1通过了两个typeof if语句,第二次通过了两个if语句。 Can anybody help me understand and hopefully try and catch the specific nullable instance of the date time? 有人可以帮助我理解并希望尝试捕获日期时间的特定可空实例吗?

To note i have also tried switching to a definition and test on Nullable just in case, but it made no difference. 要注意的是,我还尝试切换到Nullable的定义并进行测试,以防万一,但这没什么区别。

Many thanks! 非常感谢!

The answer is you can't. 答案是你做不到。

If you have an object date there is no way to know if it orginally comes from a nullabe DateTime or not. 如果您有object date ,则无法知道它最初是否来自nullabe DateTime

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

The assignment to o is morally equivalent to o的赋值在道德上等同于

object temp = null;

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

o = temp;

As you can see, the information of the nullable type is lost and what you are really getting is the boxed nullable's value. 如您所见,可为空类型的信息丢失了,您真正得到的是装箱的可为空的值。

This is easy to see by simply doing o.GetType() which will return DateTime if the nullable had a value or you will get a NullReferenceException if it didn't. 只需执行o.GetType()即可轻松看到它,如果nullable具有值,它将返回DateTime否则,您将获得NullReferenceException

This does not mean that you can not determine if the declared type of a property, method or member is nullable or not. 这并不意味着您无法确定属性,方法或成员的声明类型是否可为空。 You can do this easily enough via reflection. 您可以通过反射轻松地完成此操作。

First, keep in mind that testDate1 can never be null because DateTime is a struct . 首先,请记住,由于DateTimestruct ,因此testDate1永远不能为null。 If you declare a DateTime without intitializing it, it will get the default value of DateTime.MinValue . 如果您声明一个DateTime而不对其进行初始化,它将获得DateTime.MinValue的默认值。 testDate2 , on the other hand, is a Nullable struct, where the default value is null(-ish... it's actually a value that represents null, but not null itself). 另一方面, testDate2是一个Nullable结构,其中默认值为null(-ish ...它实际上是表示null的值,但本身不表示null)。

IsInstanceOfType is using o 's GetType() method in the background to verify that its type is the same as the type you are comparing to (in this case, DateTime? ). IsInstanceOfType在后台使用oGetType()方法来验证其类型是否与您要比较的类型相同(在本例中为DateTime? )。 However, if you take a look at the documentation , it states: 但是,如果您查看文档 ,它会指出:

Calling GetType on a Nullable type causes a boxing operation to be performed when the type is implicitly converted to Object. 在将类型隐式转换为Object时,对Nullable类型调用GetType会导致执行装箱操作。 Therefore GetType always returns a Type object that represents the underlying type, not the Nullable type. 因此,GetType总是返回代表基础类型的Type对象,而不是Nullable类型。

So, if you step through the foreach loop for the testDate1 property, you'll see that the first condition will return true (since testDate1 can't be null, which means it has to be of type DateTime ). 因此,如果您遍历testDate1属性的foreach循环,您将看到第一个条件将返回true(因为testDate1不能为null,这意味着它必须为 DateTime类型)。 You then step into the second if-condition (though that's effectively just doing the same check again), but you don't enter the inner if because o currently has a value of DateTime.Now . 然后,您进入第二个if条件(尽管实际上只是在再次执行相同的检查),但是由于o当前具有DateTime.Now的值,因此您无需输入内部if。

Now stepping through for testDate2 (which is holds a null value), you will see that you don't enter either of the if-conditionals because null doesn't have a type. 现在逐步执行testDate2 (它包含一个null值),您将看到您没有输入任何 if条件,因为null没有类型。 As such, your object will remain null throughout the second iteration of the loop, giving you the output you see there. 这样,您的对象将在循环的第二次迭代中保持为空,从而为您提供在那里看到的输出。


NOTE: Just so you know, the way you're "assigning" values to o doesn't modify the original TestClass at all. 注意:正如您所知,将值“分配”给o根本不会修改原始的TestClass。 Consider the following: 考虑以下:

TestClass testing = new TestClass();
var prop = typeof(TestClass).GetProperty("testDate1");

// Here we get the current value of testing.testDate1, which is the default DateTime.MinValue
object o = prop.GetValue(testing);

// Here we set o to null... has ZERO effect on testing.testDate1. 
o = null;

// What you actually want is probably the following.
// (Remember though that testDate1 can't be null... this just sets it back to DateTime.MinValue.)
prop.SetValue(testing, null);

Thank you for so much useful comments and links. 感谢您提供这么多有用的评论和链接。 I realise that it was the property i should have been inspecting and not the object. 我意识到这是我应该检查的属性,而不是对象。 I am using this: 我正在使用这个:

Nullable.GetUnderlyingType(p.PropertyType)

It allows me to determine what i am dealing with and is pretty effective. 它使我能够确定我要处理的内容并且非常有效。 I still end up switching on typeof(T).Name but i will cross that bridge when i come to it :) 我仍然最终打开typeof(T).Name,但是当我遇到它时,我会越过那座桥:)

I have to live with the fact that functional code vs ugly code remains an internal battle! 我必须忍受这样的事实,即功能代码与丑陋代码仍然是一场内战!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM