Guy
Guy

Reputation: 67340

LINQ dependent calculation assignment

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

Upvotes: 4

Views: 632

Answers (2)

Amy B
Amy B

Reputation: 110161

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

Upvotes: 5

Erik Forbes
Erik Forbes

Reputation: 35871

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.

Upvotes: 8

Related Questions