Well, sonny is me, actually.
I spent quite a long time trying to understand why my LINQ average function wasn’t working.
Paring down to a simple example, I wanted to check the average of a filtered subset of data.
Say my data is an array if integers:
int[] nums = { 84, 123, 101, 94, 238 };
I can get the average of these by calling:
var numavg=nums.Average(); –returns 128.0
I then wanted to get the average of only those numbers that were greater than 100.
But wait, I really started this in VB! So I was writing this function:
Dim avgnums = mynums.Average(Function(n) n > 100)
Which compiled and ran, but returned -0.333333333333.
I looked at it inside and out, over and under and could not figure out what was going on.
so then I tried it in C# and got this compiler error:
Cannot convert lambda expression to delegate type ‘System.Func<int,int>’ because some of the return types in the block are not implicitly convertible to the delegate return type
Finally I noticed the other error listed in the Errors window:
Cannot implicitly convert type ‘bool’ to ‘int’
And realized the error of my ways.
I was thinking that my lambda was for filtering, but all I was doing was an eval which was returning trues and falses depending on whether the value was >100 or not. And the average function was the same as Average(0,0,0,0,-1,-1) which is -2/6. So -0.333333333 was correct!
[note – Option Strict was off which imacted this – see additional comments at the end of this post]
So what is the correct way to do what I wanted? I need a filtering method, duh!
in C#:
var numavg3 = nums.Where(q => q > 100).Average();
in VB
Dim avgnums2 = mynums.Where(Function(n) n > 100).Average(Function(n) n)
About VB’s Option Strict in this example
As Bill McCarthy points out, Option Strict=On would have caught the attempt to use a boolean in the Average function, forcing me to specifiy the types in the array, which I *had* in fact done in the C# code, (because it forced me to). Option Strict is one of those things you need to change to “ON” after you install Visual Studio. I had missed it in this installation and because I was focused on what I was doing wrong with the lambdas, it hadn’t even occurred to me.
Dim mynums() As Integer = {10, 20, 40, 100, 120, 140}
Otherwise, he compiler tells you: “Option Strict on requires all variable declarations to have an ‘As’ clause.” Which is a lie. There are cases where it is required and cases where it is not. Note my VB code for calculating the average is still valid and avgnums2 is recognized as a Double at compile time.
On the other hand, VB’s implicit casting is still in play as is demonstrated by then taking that double and concatenating it with a string.
Dim x = avgnums2 & “xya”