是否有可能在链中调用动态对象实现,如果遇到空引用的路径中的任何位置,而不抛出任何异常,则保持空引用结束?在链式空引用上调用trygetmember
a.b.c.e
例如:如果是空值,则a.b.c.e为空,或者如果c为null C.E为null等?
非常喜欢哈斯克尔的Maybe monad。
是否有可能在链中调用动态对象实现,如果遇到空引用的路径中的任何位置,而不抛出任何异常,则保持空引用结束?在链式空引用上调用trygetmember
a.b.c.e
例如:如果是空值,则a.b.c.e为空,或者如果c为null C.E为null等?
非常喜欢哈斯克尔的Maybe monad。
您可以做类似的事情,但不是最外层的对象,即如果a
为空,则无法访问a.b
。
您可以创建A
类的空实例,该实例返回所有属性的空实例。然后a.b
将返回一个B
的空实例,对于c
属性将返回一个空实例C
,e
属性将返回一个空实例E
。
你不会得到一个空值,但你会得到一个空的情况下,您可以用检查:
E e = a.b.c.e;
if (e != E.Empty) { ... }
如果任何沿途的属性返回一个空的情况下,最终的结果会是E.Empty
。
public class A {
public B b;
public A(B newB) { b = newB; }
private static A _empty = new A(B.Empty);
public static A Empty { get { return _empty; }}
}
public class B {
public C c;
public B(C newC) { c = newC; }
private static B _empty = new B(C.Empty);
public static B Empty { get { return _empty; } }
}
public class C {
public E e;
public C(E newE) { e = newE; }
private static C _empty = new C(E.Empty);
public static C Empty { get { return _empty; } }
}
public class E {
public string name;
public E(string newName) { name = newName; }
private static E _empty = new E(null);
public static E Empty { get { return _empty; } }
}
例子:
A a1 = new A(new B(new C(new E("Hello world!"))));
A a2 = new A(new B(new C(E.Empty)));
A a3 = new A(B.Empty);
E e1 = a1.b.c.e; // e1.name returns "Hello world!"
E e2 = a2.b.c.e; // e2 == E.Empty
E e3 = a3.b.c.e; // e3 == E.Empty
感谢您提供非常详细的答案! – 2010-10-22 18:42:42
检查这篇大文章:Chained null checks and the Maybe monad
一个伟大的很多程序员都满足的情况下,在访问一个嵌套的对象属性(例如,person.Address .PostCode),他们必须做几次空的检查。这个需求经常在XML解析中弹出,当你尝试访问它们(并且随后尝试访问Value时抛出一个NullReferenceException)时,缺失的元素和属性可能返回null。在本文中,我将介绍如何使用C#中的Maybe monad,以及使用扩展方法来提高可读性。
这是一个穷人的安全导航扩展方法,它只是在try catch中包装表达式以寻找nullref。
https://gist.github.com/1030887
public static class Extensions
{
public static TResult SafeInvoke<TModel, TResult>(this TModel model, Func<TModel, TResult> expression, TResult nullValue = default(TResult))
{
try
{
return expression(model);
}
catch (NullReferenceException)
{
return nullValue;
}
}
}
您可以相当容易地调用的代码。
public class MyModel
{
public Name Name { get; set; }
}
public class Name
{
public string First { get; set; }
public string Last { get; set; }
}
var model = new MyModel();
var firstName = model.SafeInvoke(x => x.Name.First, "john");
var lastName = model.SafeInvoke(x => x.Name.Last, "doe");
Console.WriteLine("{0}, {1}", lastName, firstName)
// prints: "doe, john"
看起来像“a.b.c.e”但行为像“a == null?null:a.b == null?null:a.b.c == null?null:a.b.c.d”? – xcud 2010-10-22 18:09:28
@xcud:是的,但我不想写所有这些==? nulls:... – 2010-10-22 18:10:21