Inizializzatori di oggetti in una query LINQ: è possibile riutilizzare i dati calcolati?

StackOverflow https://stackoverflow.com/questions/6331913

  •  27-10-2019
  •  | 
  •  

Domanda

Sto usando una query linq che sembra (dopo qualche semplificazione) qualcosa di simile al seguente:

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

Quello che mi preoccupa è l'espressione di calcolo che appare due volte, per PassedUsersNum e CompletionRate.

Supponendo che CompletionRate = (PassedUsersNum / TotalUsersNum) * 100, come posso scriverlo riutilizzando il calcolo di PassedUsersNum, invece di scrivere di nuovo quell'espressione?

È stato utile?

Soluzione

Il modo più semplice sarebbe utilizzare let per inserire prima un altro passaggio di selezione:

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'espressione verrà valutata solo una volta per gruppo, ovviamente.

Altri suggerimenti

Puoi anche semplicemente estrarre il tuo Count func in un altro metodo che restituisce un Func se vuoi, o un metodo che accetta un double e restituisce 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 */ }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top