【问题标题】:C# How to handle nullable typesC#如何处理可空类型
【发布时间】:2014-08-02 15:20:58
【问题描述】:

处理“DateTime”等可为空类型的正确方法是什么?当您需要选择 2 个可以为空且其中一个为空的日期中较小的一个时, 将不会做,因为将空与实际日期进行比较会导致错误,例如:

DateTime? function( DateTime? a, DateTime? b ){
    return a < b ? a : b;
}

如果 a 或 b 为空,则返回 b。

我必须使用 if 语句还是有解决方法?

编辑:如果其中一个值为 null,我希望返回 not-null

编辑:如果我使用函数作为示例令人困惑,我很抱歉。这并不是说我想避免使用 if 语句。但是可以为空的 DateTimes 之间有很多比较,我想避免创建需要显式调用等的自定义比较器。

是否可以覆盖默认日期时间?比较器?

【问题讨论】:

  • 如果参数之一为空或两者都为空,函数必须返回什么?
  • 你想要发生什么?
  • 这完全取决于您的应用程序认为空日期的含义:空日期是否小于所有实际日期?比所有真实日期都大?是否为您的应用程序定义了“null
  • @MichaelEdenfield 我希望为任一比较(大于和小于)返回非空值

标签: c# comparison


【解决方案1】:

你可以使用Nullable.Compare

static DateTime? GetLowerDateTime(DateTime? a, DateTime? b)
{
    int val = Nullable.Compare(a, b);
    if (val < 0) return a ?? b;
    if (val > 0) return b ?? a;
    return a; //whichever you want to return if they're equal
}

【讨论】:

  • 或者更简洁一点:return Nullable.Compare(a, b)
  • @PiotrekDakanowski +1,很好。
  • @AlexD - 你说得对,我错过了关于不返回空值的补充。我已经更新了答案。 ——
  • @keyboardP 太棒了!或者,为了便于阅读,return val &lt; 0 ? a ?? b : val &gt; 0 ? b ?? a : a != null ? a : null/*or whatever for null-null case*/ :-)。
【解决方案2】:
DateTime? function( DateTime? a, DateTime? b ){
    if(!a.HasValue && !b.HasValue)
        throw new ArgumentNullException();
    else if(!a.HasValue)
        return b;
    else if(!b.HasValue)
        return a;

    return a.Value < b.Value ? a : b;
}

逻辑:

  1. 如果两个值都是null,则抛出异常。
  2. 如果 A 或 B 是 null,则返回另一个。
  3. 如果 A 或 B 都不是 null,则返回小于另一个的那个。

【讨论】:

  • 所以没有解决方法,我必须坚持使用 if 语句?
  • if 语句是一种明确的方式,一旦你有null DateTime 的组合,你打算发生什么。由于您已经知道希望函数如何将 null DateTime 与具有值的 DateTime 进行比较,因此您可以this answer 中那样重载运算符。
  • @Scorpion 谢谢天蝎座,我不知道你可以在课堂外覆盖比较器。
  • 您为什么不能将nullnull 进行比较?他们是平等的。比较它们是合法的。你的函数不应该抛出。
  • @Scorpion 我有点坚持在课堂外覆盖运算符,因为人们到处都说这是不可能的。
【解决方案3】:

你需要弄清楚在你的函数被调用的每一种情况下你想要发生什么,然后编写代码来做那件事。我有点担心您正在寻找“编写 if 语句”的“解决方法”,好像 if 语句是邪恶的,您不应该使用它们?不要试图变得聪明或鬼鬼祟祟——你可能正在编写一个需要工作可维护的应用程序,而不是参加代码高尔夫比赛。

相反,您应该遵循this answer 中的优秀建议:明确您的函数需要如何工作,然后准确地实施规范。清晰准确。

您的函数有四种可能的输入组合,您需要弄清楚每种输入的返回值是什么。从您的编辑来看,您似乎希望该函数尽可能多地返回一个非空值,以便让事情变得简单:

  1. function(a, b):返回ab中较小的那个。
  2. function(a, null):必须返回a
  3. function(null, b):必须返回b
  4. function(null, null):必须返回null

所以,我们这样写:

DateTime? function( DateTime? a, DateTime? b )
{
    // Case 1.
    if (a.HasValue && b.HasValue)
    {
        return a < b ? a : b;
    }

    // Case 2
    if (a.HasValue)
    {
      return a;
    }

    // Case 3 & 4
    return b;
}    

【讨论】:

    【解决方案4】:

    这应该适合你:

    DateTime? function( DateTime? a, DateTime? b ){
        return a < b ? a : (b ?? a);
    }
    

    ??是空合并运算符。查看 msdn:null-coalescing operator

    编辑:删除冗余代码

    【讨论】:

    • 这在有两个 null 参数的情况下不起作用。
    • 如果两个参数都为null,它将返回null。在问题中没有指定如果两者都为空应该返回什么。
    • @Scorpion 它实际上在所有情况下都有效,尽管它有点多余:如果anull,则不会发生三元的“真正”分支,因此(a ?? b) 将始终返回@ 987654327@
    猜你喜欢
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 2013-08-13
    • 2022-08-08
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多