【问题标题】:C# coalesce operator ThrowsC# 合并运算符抛出
【发布时间】:2012-04-12 04:38:45
【问题描述】:

我有一个带有字符串属性的类。我在读取它时使用了 coalesce 运算符,因为它可能为 null,但它仍然会抛出 NullRefrenceExeption。

string name = user.Section.ParentSection.Name ?? string.Empty;

更具体地说,它的“.ParentSection”是空的,是不是因为它甚至没有“.name”?如果是这种情况,我应该先用 if 块测试“.ParentSection”吗?

我认为 Coalesce 操作员有一些我不明白的地方,希望有人能解释一下这里出了什么问题。

【问题讨论】:

标签: c# string c#-4.0 null-coalescing-operator null-coalescing


【解决方案1】:

更具体地说,它的“.ParentSection”是空的,所以它也是 因为它甚至没有“.name”?

是的。

如果是这种情况,我应该先用 if 测试“.ParentSection” 屏蔽?

是的。

【讨论】:

  • 这就是我的假设,但我坚持认为这可能是一个更优雅的解决方案。谢谢:)
  • 有一个更优雅的解决方案,叫做 Maybe Monad。看我的回答。
【解决方案2】:

您需要检查 SectionParentSection 是否为空。您可以为此使用 if 语句或编写如下扩展方法:

public static class MaybeMonad
{
    public static TOut With<TIn, TOut>(this TIn input, Func<TIn, TOut> evaluator)
        where TIn : class
        where TOut : class
    {
        if (input == null)
        {
            return null;
        }
        else
        {
            return evaluator(input);
        }
    }
}

你会像这样使用这个方法:

string name = user.With(u => u.Section)
                  .With(s => s.ParentSection)
                  .With(p => p.Name) ?? string.Empty;

我认为它比包含大量 &amp;&amp; 的 if 语句要干净得多。

进一步阅读:http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

【讨论】:

  • 谢谢,我去看看。
【解决方案3】:

您需要先检查useruser.Sectionuser.Section.ParentSection 是否为空,然后才能对user.Section.ParentSection 的属性使用空合并运算符。

【讨论】:

    【解决方案4】:

    如果访问的任何对象是null,则嵌套属性访问是不安全的,这将引发NullReferenceException。您必须显式测试外部对象是否不为空。

    例如:

    string name = string.Empty;
    if(user!=null && user.Section!=null && user.Section.ParentSection !=null)
       name = user.Section.ParentSection.Name ?? string.Empty;
    

    一般来说,我会尽量避免嵌套访问属性,你违反了Law of Demeter。一些重构可能首先使这变得不必要。

    【讨论】:

    • 我同意; public String getParentSectionName() 我敢肯定,这将是一个受欢迎的变化。
    【解决方案5】:

    ?? 运算符检查左侧是否为空,如果是则返回右侧,如果不是左侧。 在您的情况下,左侧是对象 user.Section.ParentSection 中的“名称”属性,这是 null。

    在这些情况下,要么考虑可能为 null 的内容,要么执行以下操作:

    string name = user == null 
                  || user.Section == null 
                  || user.ParentSection == null 
                  || user.Section.ParentSection.Name == null 
                     ? string.Empty 
                     : user.Section.ParentSection.Name;
    

    (是的,我知道它很丑)

    【讨论】:

      【解决方案6】:

      useruser.Sectionuser.Section.ParentSection 可能为空值。

      ?? 运算符不会阻止以下检查:

      if (user != null && user.Section != null && user.Section.ParentSection != null){
      

      确保字符串属性之前的所有内容都有效且存在,然后您可以使用??。无论您尝试多少次,都无法拨打(null).Name

      【讨论】:

        【解决方案7】:

        是的,您需要在检查 Name 之前检查 SectionParentSection 是否为空

        【讨论】:

          【解决方案8】:

          最好这样做:

          if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
          {
               string name = user.Section.ParentSection.Name ?? string.Empty;
          }
          

          【讨论】:

            【解决方案9】:

            空合并运算符采用如下语句:

            a = b ?? c;  
            

            这说的是“评估 b;如果它有一个非空值,则将其分配给 a。否则将 c 的值分配给 a”。

            但是,在 your b 中,您使用的用户对象可能为 null,其 section 对象可能为 null,其父 section 属性可能为 null,其 name 属性为可能为空。如果您想检查所有这些(通常您应该),那么您可以执行以下操作:

            string name = string.Empty;  
            if (user != null &&  
                 user.Section != null &&  
                 user.Section.ParentSection != null)  
            {  
              name = user.Section.ParentSection.Name ?? string.Empty;  
            }
            

            一旦 IF 检查失败,它将不会进一步检查,因此当您假设对象存在并尝试访问其属性之一时,您不会收到 NullReferenceException。

            【讨论】:

              猜你喜欢
              • 2019-10-19
              • 1970-01-01
              • 2011-02-13
              • 2011-04-24
              • 2012-09-23
              • 2019-04-30
              • 2011-03-26
              • 2011-12-18
              • 2010-12-19
              相关资源
              最近更新 更多