开发者

Linq "Select" Sanity Question

开发者 https://www.devze.com 2023-03-01 05:15 出处:网络
I have logic similar to the code below. It seems as though in order to check for null references like this, I have to have two separate Select statements. Could a linq ninja tell me in which way 开发者

I have logic similar to the code below. It seems as though in order to check for null references like this, I have to have two separate Select statements. Could a linq ninja tell me in which way 开发者_开发知识库a query like this could be improved?

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();

Thank you.

EDIT: Cleaned up example code a little bit.


Well, for one thing I'd change the parameter names - after the first Select, you've got a B, so why not call it 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();

At that point, I have to wonder why you've got the second Select at all... you've already got a B, so why are you creating a new one? What does the B(B old) constructor do?

If you do need the other select though, that seems okay to me. I mean, if GetB is cheap, you could always use:

List<B> bList = Globals.GetReferences(irrelevantThing)
            .Where(a => a.GetB() != null && someOtherConditions)
            .Select(a => new B(a.GetB()))
            .ToList();

... but I'm not sure I would, to be honest.


I find it slightly better looking with the query syntax and the let operator:

   var queryB = from a in Globals.GetReferences(irrelevantThing)
                let b = a.GetB()
                where b != null && someOtherConditions
                select new B(b);

   var bList = queryB.ToList()

Depends on your preferences though...

FYI in extension method syntax, the above translates to

   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();

UPDATE: just realized that you can also use the select into clause to translate the exact original query literally :

   var queryB = from a in Globals.GetReferences(irrelevantThing)
                select a.GetB() into b
                where b != null && someOtherConditions
                select new B(b);

still prefer let though...

0

精彩评论

暂无评论...
验证码 换一张
取 消