Средний метод расширения в Linq для значения по умолчанию

Кто-нибудь знает, как я могу установить значение по умолчанию для среднего? У меня есть такая строка...

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

который выдает ошибку, потому что у меня нет оценок. Если у меня нет ни одного, я хочу, чтобы среднее значение по умолчанию равнялось 0. Я думал, что это должен быть метод расширения, где я могу указать, какое значение по умолчанию должно быть.

Ответ 1

Я попробовал некоторые из этих ответов, но в итоге получал больше исключений по той или иной причине. это закончило работать для меня. Я уверен, что производительность впечатляет, но я буду пересматривать позже.

var q1 = from v in db.DbVersions select new { VersionId = v.Id, AvgScore = v.DbRatings.Average(x => x.Score) as Nullable<double> };
var q2 = from p in dbPlugins select new { Plugin = p, AvgScore = q1.Where(x => p.DbVersions.Select(y => y.Id).Contains(x.VersionId)).Average(x => x.AvgScore) as Nullable<double> };
dbPlugins = q2.OrderByDescending(x => x.AvgScore).Select(x => x.Plugin).ToList();

Ответ 2

Существует: DefaultIfEmpty.

Я не уверен, что ваши DbVersions и DbRatings есть, и какая коллекция точно имеет нулевые элементы, но это идея:

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

Обновление: (повторяя сказанное в комментариях ниже, чтобы увеличить видимость)

Если вам нужно использовать DefaultIfEmpty в коллекции типа класса, помните, что вы можете сменить запрос LINQ на проект до агрегации. Например:

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

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

Если вы не хотите/не можете создать по умолчанию Item с Value равным 0, сначала вы можете выполнить проект в int, а затем указать по умолчанию:

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

Ответ 3

Я не думаю, что есть способ выбрать значение по умолчанию, но как насчет этого запроса

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

По существу то же самое, что и у вас, но мы сначала спросим, ​​есть ли какие-либо оценки перед их усреднением. Если нет, мы возвращаем 0.