开发者

Guard against divide-by-0 in a LINQ groupby select statement

I have the following LINQ statement:

var result = CommisionDataContext.COMMISSIONS
    .Where(c.PRODUCT == 'Computer')
    .GroupBy(g => new 
        {
            CostCenter = g.COST_CENTER,
            Product = g.PRODUCT,
        }
    .Select(group开发者_JAVA技巧 => new
        {
            Revenue = group.Sum(p => p.REVENUE),
            Volume = group.Sum(p => p.VOLUME),
            Avg = group.Sum(p => p.REVENUE) / group.Sum(p => p.VOLUME),
        });

How can I guard against the Divide by zero exception which could happen, and if it does I just want Avg to be equal to 0.


To avoid summing more than necessary, you should be able to do something like this (note that your code does not compile, however):

   ...
   .Select(group => new
   {
      Revenue = group.Sum(p => p.REVENUE),
      Volume = group.Sum(p => p.VOLUME)          
   })
   .Select(item => new
   {
      item.Revenue,
      item.Volume,
      Avg = item.Volume == 0 ? 0 : item.Revenue / item.Volume
   });


Be careful because C# Double can handle Infinity values, in fact if you try

        var x = 5.0 / 0.0

you will find that x = Infinity (without Exception) and this is really different from 0! So, if you want your AVG = 0 be sure it's correct from a mathematical and representational point of view (for example I work with marketing formulas and charts and it's important to know if my AVG is a true 0 or an approximation to avoid wrong charts representation and misconception).

Anyway, this code avoids a Divide by zero Exception (you need to set AVG as Double) if you find useful the exact value of AVG operation taking care of the Infinity return value if the volumes sum is 0.

Avg = Convert.ToDouble(group.Sum(p => p.REVENUE)) / group.Sum(p => p.VOLUME))

Otherwise you can use the "check before" approach with a single evaluation.

var x = Convert.ToDouble(group.Sum(p => p.REVENUE)) / group.Sum(p => p.VOLUME));
Avg = Double.IsInfinity(x)? 0 : x;


Just replace

Avg = group.Sum(p => p.REVENUE) / group.Sum(p => p.VOLUME),

with

Avg = group.Sum(p => p.VOLUME) == 0 
    ? 0 
    : group.Sum(p => p.REVENUE) / group.Sum(p => p.VOLUME),
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜