繁体   English   中英

C# 关于代表的问题

[英]C# question about a delegate

在下面的代码中,我调用了扩展方法 [平均] 3 次。 首先使用 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;
    }
}

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

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

我建议要么使用匿名方法(首选),要么使用GetAge方法static

没有定义扩展方法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);

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

你应该标记你的代表 static (它没有实例上下文)

public static int GetAge(Person p) 

然后定义

myDelegate myDel = Person.GetAge;

或直接致电

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

暂无
暂无

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

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