Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq "Select" Sanity Question

Tags:

c#

linq

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.

like image 475
raynjamin Avatar asked Mar 21 '26 13:03

raynjamin


2 Answers

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.

like image 200
Jon Skeet Avatar answered Mar 23 '26 02:03

Jon Skeet


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...

like image 41
jeroenh Avatar answered Mar 23 '26 02:03

jeroenh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!