简体   繁体   English

C# 关于代表的问题

[英]C# question about a delegate

In the code below i am calling the extension method [average] 3 times.在下面的代码中,我调用了扩展方法 [平均] 3 次。 First with a lambda, then by an anonymous method and third via a delegate.首先使用 lambda,然后使用匿名方法,第三次使用委托。

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#.您不能在 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 .由于IEnumerable<T>.Average需要一个Func<T, int> ,这就是您需要提供的委托,不管它与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.请注意,使GetAge成为实例方法(与 static 方法相比)没有意义,因为它返回作为参数传递的 object 的年龄,而不是父级( this ) ZA8CFDE6331BD59EB6666F891ZB41。

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).当您查看myPerson object 时,这一点变得很明显,它使用“虚拟”值进行实例化,只是为了访问其GetAge方法,该方法不使用其任何属性(您可以简单地编写double averageAge3 = people.Average(new Person().GetAge);什么都不会改变)。

I would recommend either using an anonymous method (preferred), or making your GetAge method static .我建议要么使用匿名方法(首选),要么使用GetAge方法static

There is no overload defined of extension method Average() that takes an argument of type myDelegate .没有定义扩展方法Average()的重载,它采用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 .您必须使用Func<T,TReturn>而不是myDelegate使其工作。

Example:例子:

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

You can do double averageAge3 = myDel.Invoke(myPerson);你可以做double averageAge3 = myDel.Invoke(myPerson); Or how exactly you want it to look like?或者您希望它看起来如何?

you should mark your delegate static (it has got no instance context)你应该标记你的代表 static (它没有实例上下文)

public static int GetAge(Person p) 

then define然后定义

myDelegate myDel = Person.GetAge;

or call directly或直接致电

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM