I'm creating an array of object based on data rows as shown below. While working, it bothers me a bit that I do as assignment to several fields by pulling the same value from a cell in the row. Usually, this thing would be pre-prepared before a loop and then just set multiple times but here, I don't obtain the value until inside the actual iteration.
return table.Rows.Cast<DataRow>()
.Select(row => new Beep
{
Uno = HeavyComputation(row["ID"]),
Duo = HeavyComputation(row["ID"])
}).ToList();
Can this be addressed in a better way? Something like (just daydreaming here) so?
return table.Rows.Cast<DataRow>()
.Preset("int preComputed = HeavyComputation(row['ID'])"
.Select(row => new Beep
{
Uno = preComputed,
Duo = preComputed
}).ToList();
Please note that the actual example is a bit more complex and the above code is the minimal exemplification of the issue. I do realize that Uno and Duo here are redundant. :)
In a query expression, you can use let
for this:
return from DataRow row in table.Rows
let preComputed = HeavyComputation(row["ID"])
select new Beep
{
// Use row and preComputed here
};
To have the same effect in a non-query-expression, you can use multiple Select
calls:
return table.Rows.Cast<DataRow>()
.Select(row => new { row, preComputed = HeavyComputation(row["ID"]) })
// Other stuff here if you want
.Select(pair => new Beep {
Uno = pair.preComputed,
Duo = pair.preComputed,
Trio = pair.Row[...]
});
If you only need preComputed
in the final Select
you could just use:
return table.Rows.Cast<DataRow>()
.Select(row => HeavyComputation(row["ID"]))
.Select(preComputed => new Beep {
Uno = preComputed,
Duo = preComputed
});
And if you're happy to have statement lambdas (instead of expression lambdas) then you can use Klaus's approach, of course. Bear in mind that that won't work for things like LINQ to SQL though - it only works with Enumerable
and statement lambdas can't be converted into expression trees.
See more on this question at Stackoverflow