C#关于委托的问题

3
在下面的代码中,我调用了扩展方法 [average] 三次。 首先是使用lambda,然后是使用匿名方法,第三次是通过委托。
使用委托的方式不起作用。有人能解释一下为什么吗?
非常感谢!
-----------代码--------------
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个回答

9

在C#中,你不能从一个委托类型转换到另一个委托类型。由于IEnumerable<T>.Average期望一个Func<T, int>,所以无论myDelegate是否具有相同的签名,你都需要提供该委托。

你可以更改以下内容:

myDelegate myDel = new myDelegate(myPerson.GetAge);

into:

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方法static

2

没有定义一个接受 myDelegate 类型参数的扩展方法 Average() 的重载。

适用于您情况的是以下方法:

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

0

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

public static int GetAge(Person p) 

然后定义

myDelegate myDel = Person.GetAge;

或直接拨打电话

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

0
你可以这样做:double averageAge3 = myDel.Invoke(myPerson); 或者你想让它看起来怎么样?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接