Object initializers in a LINQ query - can calculated data be reused?

I am using a linq query that looks (after some simplification) as follows:

List<UserExams> listUserExams = GetUserExams(); var examData = from userExam in listUserExams group by userExam.ExamID into groupExams select new ExamData() { ExamID = groupExams.Key, AverageGrade = groupExams.Average(e => e.Grade), PassedUsersNum = groupExams.Count(e => /* Some long and complicated calculation */), CompletionRate = 100 * groupExams.Count(e => /* The same long and complicated calculation */) / TotalUsersNum }; 

I am worried about a calculation expression that appears twice for PassedUsersNum and CompletionRate.

Assuming CompletionRate = (PassedUsersNum / TotalUsersNum) * 100 , how can I write it by re-using the PassedUsersNum calculation, instead of writing this expression again?

+4
source share
2 answers

The easiest way is to use let for the first step of the selection:

 List<UserExams> listUserExams = GetUserExams(); var examData = from userExam in listUserExams group by userExam.ExamID into groupExams let passCount = groupExams.Count( /* long expression */) select new ExamData() { ExamID = groupExams.Key, AverageGrade = groupExams.Average(e => e.Grade), PassedUsersNum = passCount, CompletionRate = 100 * passCount / TotalUsersNum }; 

The expression will be evaluated only once for each group, of course.

+6
source

You can also just extract your fun func into another method that returns Func if you want, or a method that accepts double and returns bool.

 List<UserExams> listUserExams = GetUserExams(); var examData = from userExam in listUserExams group by userExam.ExamID into groupExams select new ExamData() { ExamID = groupExams.Key, AverageGrade = groupExams.Average(funcMethod()), PassedUsersNum = groupExams.Count(e => traditionalMethod(e)), CompletionRate = 100 * groupExams.Count(e => /* The same long and complicated calculation */) / TotalUsersNum }; // later... private Func<double,bool> funcMethod(){ return e=> /* your calculation */ } private bool traditionalMethod(double d){ return /* your calculation */ } 
+1
source

All Articles