Clearing a simple foreach with linq

The next method is quite simple, I am trying to determine the position rate by matching another property of the string to find the parent. I dislike this somewhat and am looking for elegant solutions to make the method smaller, more efficient, or both. He works in this current state and he doesn't like it noticeably inefficient or whatever. This is not a critical mission or anything more curiosity.

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

      

I love the idea of ​​using it List<T>.ForEach()

, but I'm having trouble compressing it so it is still easy to read / maintain. Any thoughts?

0


a source to share


3 answers


Something like this should do it (untested!):

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();

      



Or (assuming only one speed can match), the connection will be even neater:

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();

      

+4


a source


Okay, well how about this:

// 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();

      



The advantage is that you don't have to go through a potentially large list of contract rates every time - you create a search once. Of course, this is not a problem.

+2


a source


Omit check rates != null

. The linq query can be empty, but not null

. If you only want the first element of the list, use List.First

or List.FirstOrDefault

.

No advantage in use List<T>.ForEach

.

0


a source







All Articles