我的逻辑类似于下面的代码。好像为了检查这样的空引用,我必须有两个单独的Select语句。 linq忍者可以告诉我这样的查询可以改进吗?
List<C> cList = Globals.GetReferences(irrelevantThing) // GetReferences returns List<A>, which are references to B
.Select(a => a.GetB()) // GetB returns type B, can be null
.Where(b => b != null && someOtherConditions)
.Select(c => new C(b)) // C Constructor cannot have a null parameter
.ToList();
谢谢。
编辑:稍微清理一下示例代码。
答案 0 :(得分:5)
好吧,首先我要更改参数名称 - 在第一个Select
之后,你有一个B,那么为什么不把它称为b
?
List<B> bList = Globals.GetReferences(irrelevantThing)
.Select(a => a.GetB()) // GetB returns type B, can be null
.Where(b => b != null && someOtherConditions)
.Select(b => new B(b))
.ToList();
那时候,我不得不想知道为什么你有第二个Select
...你已经有了B,所以你为什么要创建一个新的? B(B old)
构造函数做了什么?
如果你做需要另一个选择,那对我来说似乎没问题。我的意思是,如果GetB
便宜,你可以随时使用:
List<B> bList = Globals.GetReferences(irrelevantThing)
.Where(a => a.GetB() != null && someOtherConditions)
.Select(a => new B(a.GetB()))
.ToList();
......但是老实说我不确定。
答案 1 :(得分:2)
我发现使用查询语法和let
运算符看起来稍微好一些:
var queryB = from a in Globals.GetReferences(irrelevantThing)
let b = a.GetB()
where b != null && someOtherConditions
select new B(b);
var bList = queryB.ToList()
取决于您的偏好......
FYI在扩展方法语法中,上面转换为
var queryB = Globals.GetReferences(irrelevantThing)
.Select(a => new { a, b = a.GetB() })
.Where(x => x.b != null && someOtherConditions)
.Select(x => new B(x.b))
.ToList();
更新:刚才意识到您还可以使用select into
子句从字面上翻译确切的原始查询:
var queryB = from a in Globals.GetReferences(irrelevantThing)
select a.GetB() into b
where b != null && someOtherConditions
select new B(b);
仍然喜欢let
但是......