2

我有一个带有字符串属性的类。我在读取它时使用了合并运算符,因为它可能为空,但它仍然给我一个 NullRefrenceExeption。

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

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

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

4

9 回答 9

7

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

是的。

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

是的。

于 2012-03-28T14:49:53.823 回答
4

您需要检查是否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;

我认为它比带有很多&&.

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

于 2012-03-28T14:59:17.417 回答
3

在对 的属性使用空合并运算符之前user,您需要检查是否user.Section为空。user.Section.ParentSectionuser.Section.ParentSection

于 2012-03-28T14:50:32.440 回答
3

如果访问的任何对象是nullthis 将抛出一个NullReferenceException. 您将必须显式测试外部对象是否不为空。

例如:

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

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

于 2012-03-28T14:50:47.407 回答
2

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

在这些情况下,要么考虑什么可能是空的,要么做这样的事情:

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

(是的,我知道这很丑)

于 2012-03-28T14:52:11.073 回答
1

机会是useruser.Section或是user.Section.ParentSection空值。

??操作员不会阻止以下检查:

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

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

于 2012-03-28T14:50:50.943 回答
0

是的,您需要在检查之前检查是否为SectionParentSectionName

于 2012-03-28T14:53:09.883 回答
0

最好这样做:

if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
{
     string name = user.Section.ParentSection.Name ?? string.Empty;
}
于 2012-03-28T14:53:40.373 回答
0

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

a = b ?? c;  

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

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

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

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

于 2012-03-28T15:04:41.140 回答