views:

187

answers:

2

I'm using the following pattern in C#:

IList<foo> x = y.Select(a => new foo
{
    b = Calc1(),
    c = Calc2()
}).ToList();

foreach(foo f in x)
{
    f.d = b / c;
}

What I would like to do though is:

IList<foo> x = y.Select(a => new foo
{
    b = Calc1(),
    c = Calc2()
    d = b / c;
}).ToList();

So the question is: How can you modify this pattern to allow the assignment of a value that is dependent on other values being calculated during the assignment?

(Somebody will probably point out that d should be a property that does the calculation and return a value. This is a contrived example. Assume that the value of d is calculated using other values in addition to c & b which are not available later.)

+7  A: 

If you expand this to use the full LINQ syntax:

IList<foo> x = (from a in y
                let bq = Calc1()
                let cq = Calc2()
                select new foo {
                    b = bq,
                    c = cq, 
                    d = bq / cq
                }).ToList();

This will get you what you want.

There was an answer recommending you repeat your method calls (ie, d = Calc1() / Calc2()) - but I would recommend against this, considering it may be possible that Calc1() and Calc2() are expensive operations, and needlessly performing them twice may have performance implications.

Erik Forbes
Very cool solution and just as good as David's +1. I marked David's as the correct solution because it was using the extension syntax I was looking for but if I could mark both as correct I'd mark this one as well. Thanks for the help Erik!
Guy
No worries =) Glad to have been able to help.
Erik Forbes
+4  A: 

You can't re-use initialized properties in an initializer.

I like Erik's technique. If the query expression syntax is a bother, you can use a full-on anonymous method.

        List<int> y = new List<int>() { 1, 2, 3, 4 };
        var x = y.Select(a =>
            {
                int b = a + 1;
                int c = a + 2;
                int d = b / c;
                return new { b = b, c = c, d = d };
            });
David B
Good example showing the Extension Method syntax - +1 =)
Erik Forbes
Thanks David - very elegant.
Guy
No extension methods here at all. :~
Ray Booysen
What do you mean, Ray? The call to 'Select' is an Extension Method call - on IEnumerable<T>
Erik Forbes
There's an extension method used, there's a lambda expression, which gets converted to an anonymous method by the compiler... it's all good stuff. We don't have to label it as any one language feature.
David B