LINQ Extension Methode Average() wirft Exception

15/06/2008 - 17:48 von Marco von Frieling | Report spam
Hallo.

Ich habe ein Problem mit der Average() Extension method. Mein Code sieht in
etwa so aus:

var foos = GetFoos(v1, v2); // IEnumerable<Foo> GetFoos(int? value1, int?
value2)
var ratedFoos = from f in foos
let ratings = from b in f.Bars
select
b.BarRatings.Average(x =>x.Score)
let score = ratings.Average()
orderby score descending
select new { Foo = f, RatingScore = score,
RatingCount = ratings.Count()};

Dabei gibt GetFoos() in Abhàngigkeit der beiden Parameter entweder exakt ein
Foo oder mind. 2 Foos zurück, und wenn nur ein Foo zurückgebenen wird, wird
in Folge offenbar Average(this IEnumerable<TSource> source) aufgerufen, wenn
es mehrere sind, Average(this IQueryable<TSource> source). Das Problem dabei
ist, dass ein Foo nicht unbedingt Bars haben muss und Bar nicht unbedingt
BarRatings, Average(IEnumerable<TSource> source) aber eine Exception wirft
wenn die Sequenz leer ist (Count == 0). Wàre es da nicht sinnvoller, einfach
0.0 zurückzugeben? Denn bei LINQ to Objects muss man ja ebenso davon
ausgehen, dass eine Ergebnismenge leer ist wie bei LINQ to SQL.

Danke und lg,
Marco
 

Lesen sie die antworten

#1 Frank Dzaebel
15/06/2008 - 19:54 | Warnen spam
Hallo Marco,

... Das Problem dabei ist, dass ein Foo nicht unbedingt Bars haben muss
und Bar nicht unbedingt BarRatings, Average(IEnumerable<TSource> source)
aber eine Exception wirft wenn die Sequenz leer ist (Count == 0). Wàre es
da nicht sinnvoller, einfach 0.0 zurückzugeben? Denn bei LINQ to Objects
muss man ja ebenso davon ausgehen, dass eine Ergebnismenge leer ist wie
bei LINQ to SQL.



Naja, was ist denn der Durchschnitt von <Nichts> ?
Da ist 0 zunàchst etwas unsauber.
Aber das "Problem" ist typisch in LINQ, nichts desto
trotz auch einfach zu lösen. Verschiedene Möglichkeiten ...

Man kann Average auch auf Nullable Typen
anwenden:

IEnumerable<int?> ints = new int?[] { }; //1,5,42
double? a = ints.Average(); // keine Exception, sondern null
// im Code ggf. mit dem ?? Operator

Es gibt auch die "*OrDefault" Methoden.
(FirstOrDefault, LastOrDefault, SingleOrDefault,
Das ist eigentlich noch gàngiger.

Für Deinen Fall zum Beispiel ggf. am sinvollsten
wohl: DefaultIfEmpty:

IEnumerable<int> ints = new int[] { }; //1,5,42
double a = ints.DefaultIfEmpty().Average();


ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Ähnliche fragen