处理对象层次结构中空引用的更好方法

时间:2009-04-17 07:39:33

标签: .net null nullreferenceexception

我正在寻找一种处理对象层次结构中空引用的好方法。

即:

if(null == Object1.Object2.Object3.Property)

如果说Object2为null,则此示例将抛出Null Reference异常。

在我的情况下,我不在乎什么是null,只是有些东西。 我真的不想在我希望做这样的事情的每个地方放置尝试/捕获,所以我一直在寻找替代方案。

我已经尝试过??运算符,但这会在两个级别之后产生一些难看的代码。

任何想法都赞赏。

6 个答案:

答案 0 :(得分:6)

现在这可能正在切线......但我建议改变设计以避免丑陋和痛苦

致电Object1.Object2.Object3.Property会违反law of demeter。相反,如果您应该访问该属性,Object1应该公开一个Property本身...所以你应该调用Object1.RetrievedFromTheDepthsProperty
为什么需要这样做..如果Type Object2的设计者将'Object3'字段/属性返回的Object的类型更改为没有您正在寻找的Property的那个,那么您将被清除。客户端对Object1的内部结构了解太多。如果将Object1封装在数据位于内部的位置,则可以安全地防范将来的更改。此属性也可以根据需要在内部执行所有空值检查...让您更清晰

if (Object1.RetrievedFromTheDepthsProperty == null) {...}

答案 1 :(得分:2)

这种(零安全解除引用)偶尔会被提升,而不是;目前没有整洁的答案,除了:

if(Object1 == null || Object1.Object2 == null
        || Object1.Object2.Object3 == null
        || Object1.Object2.Object3.Property == null)

如果你需要(通过引入变量),你可以做一些小的缓存,但这甚至更加丑陋:

SomeType2 obj2;
SomeType3 obj3;
if(Object1 == null || (obj2 = Object1.Object2) == null
        || (obj3 = obj2.Object3) == null
        || obj3.Property == null)

一般情况下,除非你确实真的不想两次调用一个属性(因为它比一个属性应该做的更多),否则我会反对上述内容。

答案 2 :(得分:2)

您可以使用Null Object pattern

class Car {
    Engine engine = null;

    public Engine Engine { 
        get { 
            return engine ?? new NullEngine();
        }
    }
}

class Engine {
    string make;
    public virtual string Make { get { return make; } }
}

class NullEngine : Engine {
    public override string Make { get { return null; } }
}

然后你可以这样做:

Car car;
if (car.Engine.Make != null) Console.WriteLine(car.Engine.Make);

而不是:

Car car;
if (car.Engine != null && car.Engine.Make != null) Console.WriteLine(car.Engine.Make);   

请注意,为整个模型定义“null对象”需要做很多工作。您还需要非常小心,以免混淆模型的用户。如果你传递null并且忘记检查它,代码往往会迅速爆炸,但是“null对象”可以更容易地存在于callstack深处并导致细微问题,因为它不是真正的对象。

答案 3 :(得分:1)

不直接回答你的问题 - 只是一些提示:

  • 尝试使用Null object
  • 到目前为止(你的三个级别)通过层次结构似乎不合适,也许第一/第二级的某些方法会回答这个条件会有所帮助

答案 4 :(得分:0)

通常,如果您不关心对象层次结构中哪个属性为null,则不要对其进行测试。为应用程序使用全局错误处理程序(这将取决于应用程序类型ASP.NET,WinForms,...)并说出用户出错了。

答案 5 :(得分:0)

我强烈建议您查看以下帖子: http://www.hardcodet.net/2008/12/observe-dependencies-through-lambda-expressions-part1

它指的是类似的问题,也可以让您轻松处理更改。