Limpando um foreach simples com linq

votos
0

O método a seguir é muito simples, eu estou tentando determinar uma taxa de item de linha, combinando-se outra propriedade do item de linha com uma pesquisa de um objeto pai. Há algumas coisas que eu não gosto sobre isso e estou à procura de soluções elegantes que quer fazer o método de menor, mais eficiente, ou ambos. Ele funciona em seu estado atual e não é como ele é notavelmente ineficientes ou nada. Isto não é de missão crítica ou qualquer coisa, mais uma curiosidade.

    private decimal CalculateLaborTotal()
    {
        decimal result = 0;

        foreach (ExtraWorkOrderLaborItem laborItem in Labor)
        {
            var rates = (from x in Project.ContractRates where x.ProjectRole.Name == laborItem.ProjectRole.Name select x).ToList();
            if (rates != null && rates.Count() > 0)
            {
                result += laborItem.Hours * rates[0].Rate;
            }
        }
        return result;
    }

Eu gosto da idéia de usar List<T>.ForEach(), mas eu estava tendo alguns problemas mantendo-sucinta o suficiente para ainda ser de fácil leitura / manter. Alguma ideia?

Publicado 19/05/2009 em 20:12
fonte usuário
Em outras línguas...                            


3 respostas

votos
4

Algo como isso deve fazê-lo (não testado!):

var result = 
    (from laborItem in Labor
     let rate = (from x in Project.ContractRates 
                 where x.ProjectRole.Name == laborItem.ProjectRole.Name 
                 select x).FirstOrDefault()
     where rate != null
     select laborItem.Hours * rate.Rate).Sum();

Ou (assumindo que apenas uma taxa pode combinar) uma junção seria ainda mais puro:

var result = 
    (from laborItem in Labor
     join rate in Project.ContractRates
         on laborItem.ProjectRole.Name equals rate.ProjectRole.Name
     select laborItem.Hours * rate.Rate).Sum();
Respondeu 19/05/2009 em 20:18
fonte usuário

votos
2

Ok, bem como sobre isto:

// Lookup from name to IEnumerable<decimal>, assuming Rate is a decimal
var ratesLookup = Project.ContractRates.ToLookup(x => x.ProjectRole.Name,
                                                 x => x.Rate);

var query = (from laborItem in Labor
             let rate = ratesGroup[laborItem].FirstOrDefault()
             select laborItem.Hours * rate).Sum();

A vantagem aqui é que você não precisa de olhar através de um potencialmente grande lista de taxas de contrato de cada vez - você constrói a pesquisa uma vez. Isso pode não ser um problema, é claro.

Respondeu 19/05/2009 em 20:23
fonte usuário

votos
0

Omitir o rates != nullcheck - uma consulta LINQ pode estar vazio, mas não null. Se você só precisa o primeiro elemento de uma lista, use List.Firstou List.FirstOrDefault.

Não há nenhuma vantagem em usar List<T>.ForEach.

Respondeu 19/05/2009 em 20:23
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more