比较可空的DateTime?

46

寻找一种比以下方式更好的比较可空日期时间的方法:

有什么建议吗?

// myobject.ExpireDatetime is of DateTime?
//
if (!myobject.ExpireDateTime.IsNull() && DateTime.Compare((DateTime)myobject.ExpireDateTime, DateTime.Now.ToUniversalTime()) < 0)
{ //error! }    

已编辑:抱歉引起了混淆……我的对象 ExipreDatetime 是 DateTime 类型。


在C#中,**object**是一个关键字,不能用作标识符(除非你将其写成@object)。我认为如果你有一个装箱的DateTime可能是空引用,或者你有一个未装箱的“真正”的可空DateTime(DateTime?),这是不清楚的。 - Jeppe Stig Nielsen
这个回答解决了你的问题吗?比较可空的日期时间对象 - Michael Freidgeim
5个回答

57

你的问题对我来说不是非常清楚,但如果我们有

DateTime? ExpireDateTime;  // could be a variable or a property

只说这个也没关系。

if (ExpireDateTime < DateTime.UtcNow)
{
  ...
}

如果ExpireDateTime为空(HasValue为false),这将是可以的。一些缺乏经验的开发人员可能会难以理解lifted operators,因此为了更清晰明了,您可以写成:

if (ExpireDateTime < (DateTime?)DateTime.UtcNow)
{
  ...
}

内容相同,但更易于阅读和理解。

当可空类型可能为空时.Value不能被写入。如果这样做,会得到一个 InvalidOperationException 异常,异常信息为 "Nullable object must have a value"


太棒了!是的,这正是我真正需要的解释。也就是说,如何比较可空日期时间而不通过检查值是否为null来短路逻辑...然后检查可空值的约束条件 <伪代码> if (val.isnotnull && val.iswithinconstraint) - genxgeek
2
但是,(default(DateTime?) < DateTime.UtcNow)为假,而(default(DateTime?) > DateTime.UtcNow)也为假。 - labroo
3
当然。因此,使用可空类型时,我们没有“三分法”,因此有时x<yx==yx>y都是false - Jeppe Stig Nielsen
这也取决于具体的业务需求。在某些情况下,我可能希望将空日期视为“大于”任何有效日期。例如:minDate = d1 < d2 ? d1 : d2,其中所有三个日期都可为空 - 在这种情况下,如果有任何实际有效日期,则希望minDate接收该日期,但不是空值,除非d1和d2都为空。 - JustAMartin
@JustAMartin 如果你真的想要,你可以写 !(ExpireDateTime >= DateTime.UtcNow),这与 ExpireDateTime < DateTime.UtcNow 相同,如果没有涉及到 null,但当涉及到 null 时,它的值相反。然而,根据个人喜好,可能更容易阅读类似于 !ExpireDateTime.HasValue || ExpireDateTime.Value < DateTime.UtcNow 的内容。 - Jeppe Stig Nielsen

40

我建议您使用以下内容:

int y = Nullable.Compare<DateTime>(DateTime.UtcNow, x); 

// x is the nullable date time object.
// y will be '-1' if x is greater than DateTime.UtcNow

12
编译器提升变量并生成代码以检查空值。
> new DateTime?()
null
> DateTime.Now > null
false
> DateTime.Now < null
false

> new int?()
null
> 10 >= null
false
> 10 =< null
false
> 10 == null
false
> 10 != null
true

了解这一点后,您可以编写简单的代码。

// d is a DateTime? 
DateTime now = DateTime.Now;

bool after = d > now;
bool before = d < now;
bool today = d?.Date == now.Date;

如果 d 为 null,则所有内容都将为 false,否则它将像正常的 DateTime 比较一样工作。


4
如果 ExpireDateTime 是一个 Nullable<DateTime>,我会采取以下方法:
if (ExpireDateTime.HasValue && ExpireDateTime < DateTime.Now.ToUniversalTime())
{ 
}

1

使用可空类型的 Value 属性:

objet.ExpireDateTime.Value

if (!object.ExpireDateTime.IsNull() 
    && DateTime.Compare(objet.ExpireDateTime.Value, 
                        DateTime.Now.ToUniversalTime()) < 0)
{ 
}    

原问题仍然存在一些痕迹,因为(在通常的实现中)System.Object没有名为ExpireDateTime的静态成员(因此它仍无法编译)。 - Jeppe Stig Nielsen
@JeppeStigNielsen - ExpireDateTime 可能是一个扩展方法。 - Oded
@Oded 你不能这样扩展。即使使用扩展方法,你也需要在点号(.)之前加上标识符或普通表达式。例如 (new object()).ExpireDateTime()typeof(object).ExpireDateTime()@object.ExpireDateTime() 都可能与某些(非常疯狂的)扩展方法编译。但是只有 object 是有问题的。此外,如果它是一个方法,你不能仅仅说 .IsNull 而不先调用 ExpireDateTime。简而言之,它永远不可能作为有效的存在。 - Jeppe Stig Nielsen
抱歉有些混淆,object.ExpireDateTime 是 DateTime 类型。 - genxgeek
@JaJ 在代码中写object的“点”ExpireDateTime是不合法的。 - Jeppe Stig Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接