5

elvis操作员,又名无效条件操作员,非常酷。Elvis操作员在铸造调用链中

在LINQ查询中,它与空合并“??”运营商。

Somedata.Where(dt=>(dt?.Inner?.InnerMost?.Include=="Yes")??false); 

但是,如果您需要转换中间值,您会怎么做?

对于链中的一个链接,它工作得很好。

Somedata.Where(dt=>(
    ((InnerClass)dt?.Inner) 
    ?.InnerMost)?.Include=="Yes") 
    ??false); 

但有了额外的必要的演员阵容和调用是“驱动分开”。

Somedata.Where(dt=>(
    ((InnerMostClass)   <=== Cast 
    ((InnerClass)dt?.Inner) 
    ?.InnerMost)?.Include=="Yes"))   <=== Use 
    ??false); 

可能在这里不止一次地搞砸括号,但我希望你能明白。

虽然这个“trainwreck”调用链是一种代码味道,但是有没有更具表现力的方式来提高简洁性和清晰度?

+4

这看起来好一点'(( ((dt as InnerClass)?。Inner)as InnerMostClass)?. InnerMost)?. include ==“Yes”))??假的 ' – Andrey

+1

我想不出任何更好的@Andrey解决方案,当然,其他方面当然不会写这些类型的语句。尝试尽可能多地将尽可能多的功能挤入尽可能多的线条是有趣的,但有代码的高尔夫球。对于人们需要维护的代码,我的拇指角色是,如果你不能一目了然地告诉lambda正在做什么,它应该是一个命名的函数......虽然这是个好问题... – pseudoDust

+1

我与pseudoDust :我会放弃这种说法。你不得不花费大量的脑力去研究它正在做什么是一种代码味道。另外,我会关心我在什么情况下需要投一个家长和孩子,哪一个可能是空的。 – CptCoathanger

回答

1

你可以把链接和使用非常简单的扩展方法防止括号:

dt?.Inner.As<InnerClass>()?.InnerMost.As<InnerMostClass>()?.Include == "Yes" 

有了这样定义的扩展方法:

public static class ObjectExtensions 
{ 
    public static T As<T>(this object obj) where T : class 
    { 
     return obj as T; 
    } 
} 
+0

有趣。太糟糕了,我们需要用“对象”和“:class”约束。如果我们能指出TInput需要成为TResult的接口或基类才能获得一些编译时检查,那将是很酷的。但在C#中,TInput和TResult都需要显式类型参数。最佳状态是我们只能说明TResult,但是要推断TInput。我想我的未来会有F#,除非我忘记了一些东西。 – Tormod