我正在寻找一种处理对象层次结构中空引用的好方法。
即:
if(null == Object1.Object2.Object3.Property)
如果说Object2为null,则此示例将抛出Null Reference异常。
在我的情况下,我不在乎什么是null,只是有些东西。 我真的不想在我希望做这样的事情的每个地方放置尝试/捕获,所以我一直在寻找替代方案。
我已经尝试过??运算符,但这会在两个级别之后产生一些难看的代码。
任何想法都赞赏。
答案 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)
不直接回答你的问题 - 只是一些提示:
答案 4 :(得分:0)
通常,如果您不关心对象层次结构中哪个属性为null,则不要对其进行测试。为应用程序使用全局错误处理程序(这将取决于应用程序类型ASP.NET,WinForms,...)并说出用户出错了。
答案 5 :(得分:0)
我强烈建议您查看以下帖子: http://www.hardcodet.net/2008/12/observe-dependencies-through-lambda-expressions-part1
它指的是类似的问题,也可以让您轻松处理更改。