initialiseurs d'objets dans une requête LINQ - est-il possible de réutiliser les données calculées?
-
27-10-2019 - |
Question
J'utilise un quelque chose comme la suivante requête LINQ qui semble (après une certaine simplification):
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
};
Ce qui me dérange est l'expression de calcul qui apparaît deux fois, pour PassedUsersNum et CompletionRate.
En supposant que CompletionRate = (PassedUsersNum / TotalUsersNum) * 100
, comment puis-je écrire en réutilisant le calcul de PassedUsersNum, au lieu d'écrire à nouveau cette expression?
La solution
La façon la plus simple serait d'utiliser let
pour injecter une nouvelle étape de sélection d'abord:
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
};
L'expression ne sera évaluée une fois par groupe, bien sûr.
Autres conseils
Vous pouvez également extraire seulement votre comte func dans une autre méthode qui retourne un Func si vous voulez, ou une méthode qui prend un double et retourne un 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 */ }