关于代表的C#问题

时间:2011-04-27 08:30:05

标签: c# delegates average

在下面的代码中,我调用扩展方法[平均] 3次。 首先是lambda,然后是匿名方法,第三是通过委托。

代表的方式不起作用。有人能解释我为什么吗?

提前许多人!

----------- 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;
    }
}

4 个答案:

答案 0 :(得分:9)

您无法在C#中从一种委托转换为另一种委托。由于IEnumerable<T>.Average需要Func<T, int>,这是您需要提供的委托,而不管与[{1}}具有相同签名的事实。

你可以改变这个:

myDelegate

成:

myDelegate myDel = new myDelegate(myPerson.GetAge);

或简单地将方法作为参数传递,这将为您创建适当的委托:

Func<Person, int> myDel = new Func<Person, int>(myPerson.GetAge);

请注意,使double averageAge3 = people.Average(myPerson.GetAge); // this will work 实例方法(与静态方法相比)没有意义,因为它返回作为参数传递的对象的年龄,而不是父级(GetAge)对象。

当您查看使用“虚拟”值实例化的this对象时,这变得很明显,只是为了访问其myPerson方法,该方法不使用其任何属性(你可以简单地写GetAge,什么都不会改变。

我建议您使用匿名方法(首选),或者使用double averageAge3 = people.Average(new Person().GetAge);方法GetAge

答案 1 :(得分:2)

没有定义扩展方法 Average()的重载采用类型为myDelegate的参数。

符合您案例的是:

public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector);

您必须使用Func<T,TReturn>使其有效,而不是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);

答案 2 :(得分:0)

你可以做double averageAge3 = myDel.Invoke(myPerson); 或者您希望它看起来如何?

答案 3 :(得分:0)

你应该将你的委托标记为静态(它没有实例上下文)

public static int GetAge(Person p) 

然后定义

myDelegate myDel = Person.GetAge;

或直接致电

double averageAge3 = Person.Average(myPerson.GetAge);