Average extension method in Linq for default value

Rush Frisby picture Rush Frisby · Mar 29, 2011 · Viewed 9.7k times · Source

Anyone know how I can set a default value for an average? I have a line like this...

dbPlugins = (from p in dbPlugins
                select new { Plugin = p, AvgScore = p.DbVersions.Average(x => x.DbRatings.Average(y => y.Score)) })
            .OrderByDescending(x => x.AvgScore)
            .Select(x => x.Plugin).ToList();

which throws an error becase I have no ratings yet. If I have none I want the average to default to 0. I was thinking this should be an extension method where I could specify what the default value should be.

Answer

Jon picture Jon · Mar 29, 2011

There is: DefaultIfEmpty.

I 'm not sure about what your DbVersions and DbRatings are and which collection exactly has zero items, but this is the idea:

var emptyCollection = new List<int>();
var average = emptyCollection.DefaultIfEmpty(0).Average();

Update: (repeating what's said in the comments below to increase visibility)

If you find yourself needing to use DefaultIfEmpty on a collection of class type, remember that you can change the LINQ query to project before aggregating. For example:

class Item
{
    public int Value { get; set; }
}

var list = new List<Item>();
var avg = list.Average(item => item.Value);

If you don't want to/can not construct a default Item with Value equal to 0, you can project to a collection of ints first and then supply a default:

var avg = list.Select(item => item.Value).DefaultIfEmpty(0).Average();