【问题标题】:C# question about a delegate关于委托的 C# 问题
【发布时间】:2011-04-27 08:30:05
【问题描述】:

在下面的代码中,我调用了扩展方法 [平均] 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# delegates average


    【解决方案1】:

    您不能在 C# 中从一种委托类型转换为另一种委托。由于IEnumerable&lt;T&gt;.Average 需要Func&lt;T, int&gt;,这就是您需要提供的委托,不管它与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 设为实例方法(相对于静态方法)没有意义,因为它返回作为参数传递的对象的年龄,而不是父对象(@ 987654329@) 对象。

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

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

    【讨论】:

      【解决方案2】:

      没有为扩展方法 Ave​​rage() 定义重载,该方法采用myDelegate 类型的参数。

      与您的情况相符的如下:

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

      您必须使用Func&lt;T,TReturn&gt; 而不是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);
      

      【讨论】:

        【解决方案3】:

        你可以做double averageAge3 = myDel.Invoke(myPerson); 或者您希望它是什么样子?

        【讨论】:

          【解决方案4】:

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

          public static int GetAge(Person p) 
          

          然后定义

          myDelegate myDel = Person.GetAge;
          

          或直接调用

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-12
            • 2010-12-12
            • 1970-01-01
            • 1970-01-01
            • 2014-04-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多