In the code below i am calling the extension method [average] 3 times. First with a lambda, then by an anonymous method and third via a delegate.
The way with the delegate doesn't work. Can somebody explain me why?
Many thans in advance !
-----------CODE-------------
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<Person> people = new List<Person> {
new Person { FirstName = "William", LastName = "Schokkele", Age = 35 },
new Person { FirstName = "Bill", LastName = "Gates", Age = 50 },
new Person { FirstName = "Hanne", LastName = "Schokkele", Age = 7 }
};
Person myPerson = new Person { FirstName = "Hanne", LastName = "Schokkele", Age = 7 };
myDelegate myDel = new myDelegate(myPerson.GetAge);
double averageAge= people.Average(p => p.Age);
double averageAge2 = people.Average(delegate(Person p) { return p.Age; });
double averageAge3 = people.Average(myDel); //THIS LINE DOESNT WORK. ERROR MESSAGE LIST<Person> does not contains a definition for 'average'
}
}
public delegate int myDelegate(Person p);
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public int GetAge(Person p)
{
return p.Age;
}
}
You cannot cast from one type of delegate to another in C#. Since IEnumerable<T>.Average expects a Func<T, int>, that is the delegate you need to supply, regardless of the fact that is has the same signature as myDelegate.
You can either change this:
myDelegate myDel = new myDelegate(myPerson.GetAge);
into:
Func<Person, int> myDel = new Func<Person, int>(myPerson.GetAge);
or simply pass the method as the parameter, which will create the appropriate delegate for you:
double averageAge3 = people.Average(myPerson.GetAge); // this will work
Note that making GetAge an instance method (vs a static method) doesn't make sense, since it returns the age of the object passed as a parameter, instead of the parent (this) object.
This becomes obvious when you look at the myPerson object, which is instantiated with "dummy" values, just to get access to its GetAge method, which doesn't use any of its properties (you could have simply written double averageAge3 = people.Average(new Person().GetAge); and nothing would change).
I would recommend either using an anonymous method (preferred), or making your GetAge method static.
There is no overload defined of extension method Average() that takes an argument of type myDelegate.
The one that matches your case is following :
public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector);
You have to use Func<T,TReturn> to make it work instead of myDelegate.
Person myPerson = new Person { FirstName = "Hanne", LastName = "Schokkele", Age = 7 };
Func<Person, Int32> myDel = myPerson.GetAge;
double averageAge = people.Average(p => p.Age);
double averageAge2 = people.Average(delegate(Person p) { return p.Age; });
double averageAge3 = people.Average(myDel);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With